package com.neverwinterdp.scribengin.service; import java.util.Arrays; import java.util.concurrent.atomic.AtomicLong; import com.google.inject.Inject; import com.google.inject.Singleton; import com.mycila.jmx.annotation.JmxBean; import com.neverwinterdp.registry.DataChangeNodeWatcher; import com.neverwinterdp.registry.Node; import com.neverwinterdp.registry.NodeCreateMode; import com.neverwinterdp.registry.Registry; import com.neverwinterdp.registry.event.NodeEvent; import com.neverwinterdp.registry.event.RegistryListener; import com.neverwinterdp.scribengin.dataflow.DataflowDescriptor; import com.neverwinterdp.scribengin.dataflow.DataflowLifecycleStatus; import com.neverwinterdp.scribengin.dataflow.service.VMDataflowServiceApp; import com.neverwinterdp.vm.VMConfig; import com.neverwinterdp.vm.VMDescriptor; import com.neverwinterdp.vm.client.VMClient; import com.neverwinterdp.vm.command.CommandResult; import com.neverwinterdp.vm.service.VMServiceCommand; @Singleton @JmxBean("role=scribengin-master, type=ScribenginService, name=ScribenginService") public class ScribenginService { final static public String SCRIBENGIN_PATH = "/scribengin"; final static public String EVENTS_PATH = SCRIBENGIN_PATH + "/events"; final static public String LEADER_PATH = SCRIBENGIN_PATH + "/master/leader"; final static public String DATAFLOWS_HISTORY_PATH = SCRIBENGIN_PATH + "/dataflows/history"; final static public String DATAFLOWS_RUNNING_PATH = SCRIBENGIN_PATH + "/dataflows/running"; @Inject private VMConfig vmConfig; private Registry registry; private VMClient vmClient ; private RegistryListener registryListener ; private Node dataflowsRunningNode ; private Node dataflowsHistoryNode ; private AtomicLong historyIdTracker ; @Inject public void onInit(Registry registry, VMClient vmClient) throws Exception { this.registry = registry; this.registryListener = new RegistryListener(registry); registry.createIfNotExist(EVENTS_PATH); registry.createIfNotExist(DATAFLOWS_RUNNING_PATH); dataflowsRunningNode = registry.get(DATAFLOWS_RUNNING_PATH) ; registry.createIfNotExist(DATAFLOWS_HISTORY_PATH); dataflowsHistoryNode = registry.get(DATAFLOWS_HISTORY_PATH) ; historyIdTracker = new AtomicLong(dataflowsHistoryNode.getChildren().size()); this.vmClient = vmClient; } public void onDestroy() throws Exception { } public boolean deploy(DataflowDescriptor descriptor) throws Exception { Node dataflowNode = dataflowsRunningNode.createChild(descriptor.getName(), descriptor, NodeCreateMode.PERSISTENT); dataflowNode.createDescendantIfNotExists("master/leader"); String dataflowStatusPath = getDataflowStatusPath(descriptor.getName()); registryListener.watch(dataflowStatusPath, new DataflowStatusListener(registry)); DataflowDeployer deployer = new DataflowDeployer(descriptor); deployer.start(); return true; } private VMDescriptor createDataflowMaster(DataflowDescriptor descriptor, int id) throws Exception { String dataflowAppHome = descriptor.getDataflowAppHome(); Node dataflowNode = registry.get(DATAFLOWS_RUNNING_PATH + "/" + descriptor.getName()) ; VMConfig dfVMConfig = new VMConfig() ; if(dataflowAppHome != null) { dfVMConfig.setAppHome(dataflowAppHome); dfVMConfig.addVMResource("dataflow.libs", dataflowAppHome + "/libs"); } dfVMConfig.setEnvironment(vmConfig.getEnvironment()); dfVMConfig.setName(descriptor.getName() + "-master-" + id); dfVMConfig.setRoles(Arrays.asList("dataflow-master")); dfVMConfig.setRegistryConfig(registry.getRegistryConfig()); dfVMConfig.setVmApplication(VMDataflowServiceApp.class.getName()); dfVMConfig.addProperty("dataflow.registry.path", dataflowNode.getPath()); dfVMConfig.setHadoopProperties(vmConfig.getHadoopProperties()); VMDescriptor masterVMDescriptor = vmClient.getMasterVMDescriptor(); CommandResult<VMDescriptor> result = (CommandResult<VMDescriptor>)vmClient.execute(masterVMDescriptor, new VMServiceCommand.Allocate(dfVMConfig)); return result.getResult(); } //TODO: use transaction private void moveToHistory(DataflowDescriptor descriptor) throws Exception { String fromPath = dataflowsRunningNode.getPath() + "/" + descriptor.getName(); String toPath = dataflowsHistoryNode.getPath() + "/" + descriptor.getName() + "-" + historyIdTracker.getAndIncrement(); registry.rcopy(fromPath, toPath); registry.rdelete(fromPath); } class DataflowStatusListener extends DataChangeNodeWatcher<DataflowLifecycleStatus> { public DataflowStatusListener(Registry registry) { super(registry, DataflowLifecycleStatus.class); } @Override public void onChange(NodeEvent event, DataflowLifecycleStatus status) { if(DataflowLifecycleStatus.FINISH == status) { try { Node statusNode = registry.get(event.getPath()); Node dataflowNode = statusNode.getParentNode() ; DataflowDescriptor dataflowDescriptor = dataflowNode.getDataAs(DataflowDescriptor.class); moveToHistory(dataflowDescriptor) ; } catch (Exception e) { e.printStackTrace(); } System.err.println("Scribengin service catch dataflow finish " + event.getPath()) ; setComplete(); } } }; public class DataflowDeployer extends Thread { private DataflowDescriptor descriptor; public DataflowDeployer(DataflowDescriptor descriptor) { this.descriptor = descriptor; } public void run() { try { VMDescriptor dataflowMaster1 = createDataflowMaster(descriptor, 1); //VMDescriptor dataflowMaster2 = createDataflowMaster(descriptor, 2); } catch(Exception ex) { ex.printStackTrace(); } } } static public String getDataflowPath(String dataflowName) { return DATAFLOWS_RUNNING_PATH + "/" + dataflowName; } static public String getDataflowStatusPath(String dataflowName) { return getDataflowPath(dataflowName) + "/status" ; } static public String getDataflowLeaderPath(String dataflowName) { return getDataflowPath(dataflowName) + "/master/leader" ; } }