From 3b311e850ce211e2f853df0047cdb4df0a3643ae Mon Sep 17 00:00:00 2001 From: SeokYeon Hwang Date: Wed, 13 Jan 2016 17:11:10 +0900 Subject: [PATCH] monitoring: introduce new VM monitoring architecture We introduce new running VM monitoring architecture based on java7 NIO watcher service. It should be more general service, then we apply this service to others like managing VM lists, ... Change-Id: I13cc9f50d0508629ac1a8f55ac5c11359b47d386 Signed-off-by: SeokYeon Hwang Signed-off-by: jihye424.kim --- .../tizen/emulator/manager/EmulatorManager.java | 7 +- src/org/tizen/emulator/manager/ui/MainDialog.java | 9 +- .../emulator/manager/ui/renewal/MainDialog.java | 3 - .../ui/renewal/tableviewer/VMListTableViewer.java | 7 +- .../emulator/manager/ui/widgets/VMButton.java | 7 +- .../tizen/emulator/manager/vms/EmulatorVMList.java | 23 +- src/org/tizen/emulator/manager/vms/VMLauncher.java | 39 +- src/org/tizen/emulator/manager/vms/VMProperty.java | 85 ++- .../tizen/emulator/manager/vms/VMWorkerCommon.java | 17 +- .../vms/helper/CheckingRunningEmulator.java | 568 +-------------------- .../emulator/manager/vms/helper/RefreshWorker.java | 95 ---- .../emulator/manager/vms/helper/VMSocketQueue.java | 74 --- .../emulator/manager/vms/monitor/ECSMonitor.java | 216 ++++++++ .../VMSocket.java => monitor/ECSSocket.java} | 184 ++----- .../LaunchingMonitor.java} | 123 ++--- .../manager/vms/monitor/LockFileMonitor.java | 177 +++++++ .../manager/vms/monitor/MonitoringThread.java | 83 +++ .../manager/vms/monitor/PosixLockFileMonitor.java | 150 ++++++ .../manager/vms/monitor/RunningMonitor.java | 178 +++++++ .../vms/monitor/WindowsLockFileMonitor.java | 101 ++++ 20 files changed, 1129 insertions(+), 1017 deletions(-) delete mode 100644 src/org/tizen/emulator/manager/vms/helper/RefreshWorker.java delete mode 100644 src/org/tizen/emulator/manager/vms/helper/VMSocketQueue.java create mode 100644 src/org/tizen/emulator/manager/vms/monitor/ECSMonitor.java rename src/org/tizen/emulator/manager/vms/{helper/VMSocket.java => monitor/ECSSocket.java} (53%) rename src/org/tizen/emulator/manager/vms/{helper/MonitoringEmulator.java => monitor/LaunchingMonitor.java} (68%) create mode 100644 src/org/tizen/emulator/manager/vms/monitor/LockFileMonitor.java create mode 100644 src/org/tizen/emulator/manager/vms/monitor/MonitoringThread.java create mode 100644 src/org/tizen/emulator/manager/vms/monitor/PosixLockFileMonitor.java create mode 100644 src/org/tizen/emulator/manager/vms/monitor/RunningMonitor.java create mode 100644 src/org/tizen/emulator/manager/vms/monitor/WindowsLockFileMonitor.java diff --git a/src/org/tizen/emulator/manager/EmulatorManager.java b/src/org/tizen/emulator/manager/EmulatorManager.java index ee69b3c..3640994 100755 --- a/src/org/tizen/emulator/manager/EmulatorManager.java +++ b/src/org/tizen/emulator/manager/EmulatorManager.java @@ -55,6 +55,7 @@ import org.tizen.emulator.manager.tool.SettingInfoFile; import org.tizen.emulator.manager.ui.dialog.MessageDialog; import org.tizen.emulator.manager.ui.renewal.MainDialog; import org.tizen.emulator.manager.vms.helper.WorkerLock; +import org.tizen.emulator.manager.vms.monitor.RunningMonitor; import com.sun.jna.Native; import com.sun.jna.NativeLong; @@ -81,6 +82,7 @@ public class EmulatorManager { private static boolean isWin = false; private static boolean isWin8AndAbove = false; private static boolean isLinux = false; + static { if (System.getProperty("os.name").toLowerCase().indexOf("linux") > -1) { //$NON-NLS-1$ //$NON-NLS-2$ @@ -352,24 +354,23 @@ public class EmulatorManager { CheckVT.class, CheckGPU.class, CheckSDCard.class, CheckWebcam.class); checkers.startWork(); + RunningMonitor.initialize(); } - if (!SettingInfoFile.setMACaddr()) { exitEmulatorManager(1); } - if (isConsoleMode) { EmulatorManager.startConsoleProcessor(); } else { EMLogger.getLogger().log(Level.INFO, "Start Emulator Manager!!"); //$NON-NLS-1$ + EmulatorManager.preare(); EmulatorManager.draw(); EmulatorManager.dispose(); } - } catch (Throwable e) { e.printStackTrace(); diff --git a/src/org/tizen/emulator/manager/ui/MainDialog.java b/src/org/tizen/emulator/manager/ui/MainDialog.java index 19a3a55..5e05501 100644 --- a/src/org/tizen/emulator/manager/ui/MainDialog.java +++ b/src/org/tizen/emulator/manager/ui/MainDialog.java @@ -62,8 +62,7 @@ import org.tizen.emulator.manager.ui.tabfolder.ProfileTabFolder; import org.tizen.emulator.manager.ui.tabfolder.ProfileTabItem; import org.tizen.emulator.manager.ui.widgets.ImageButton; import org.tizen.emulator.manager.vms.VMProperty; -import org.tizen.emulator.manager.vms.helper.CheckingRunningEmulator; -import org.tizen.emulator.manager.vms.helper.RefreshWorker; +import org.tizen.emulator.manager.vms.monitor.RunningMonitor; public class MainDialog { private static final String ICON_FILE_NAME = "res/em.ico"; //$NON-NLS-1$ @@ -222,7 +221,6 @@ public class MainDialog { } public void open() { - CheckingRunningEmulator.startCheckingThread(); shell.open(); SDKUpdateManager.checkUpdate(); while(!shell.isDisposed()) { @@ -242,10 +240,7 @@ public class MainDialog { public static void refreshVMPropertyList(boolean isClear) { ProfileList.settingVMPropertyList(); - // check vm socket connection - RefreshWorker.refreshVMConnect(); - // check running emulator list - CheckingRunningEmulator.refreshVMPropertyList(); + RunningMonitor.refreshAll(); if (isClear) { tabFolder.getSelection().draw(); diff --git a/src/org/tizen/emulator/manager/ui/renewal/MainDialog.java b/src/org/tizen/emulator/manager/ui/renewal/MainDialog.java index 2f120ce..18f2add 100644 --- a/src/org/tizen/emulator/manager/ui/renewal/MainDialog.java +++ b/src/org/tizen/emulator/manager/ui/renewal/MainDialog.java @@ -47,7 +47,6 @@ import org.tizen.emulator.manager.resources.StringResources; import org.tizen.emulator.manager.tool.About; import org.tizen.emulator.manager.ui.renewal.tableviewer.AbstractTableViewer; import org.tizen.emulator.manager.ui.renewal.tableviewer.VMListTableViewer; -import org.tizen.emulator.manager.vms.helper.CheckingRunningEmulator; public class MainDialog { private static final String ICON_FILE_NAME = "res/em.ico"; //$NON-NLS-1$ @@ -124,8 +123,6 @@ public class MainDialog { } public void open() { - CheckingRunningEmulator.startCheckingThread(); - shell.open(); while(!shell.isDisposed()) { if(!Display.getCurrent().readAndDispatch()) { diff --git a/src/org/tizen/emulator/manager/ui/renewal/tableviewer/VMListTableViewer.java b/src/org/tizen/emulator/manager/ui/renewal/tableviewer/VMListTableViewer.java index dd53b95..7cafca1 100644 --- a/src/org/tizen/emulator/manager/ui/renewal/tableviewer/VMListTableViewer.java +++ b/src/org/tizen/emulator/manager/ui/renewal/tableviewer/VMListTableViewer.java @@ -50,8 +50,7 @@ import org.tizen.emulator.manager.ui.renewal.MainDialog; import org.tizen.emulator.manager.ui.renewal.widgets.CreateVMCombo; import org.tizen.emulator.manager.ui.renewal.widgets.ImageButton; import org.tizen.emulator.manager.vms.VMProperty; -import org.tizen.emulator.manager.vms.helper.CheckingRunningEmulator; -import org.tizen.emulator.manager.vms.helper.RefreshWorker; +import org.tizen.emulator.manager.vms.monitor.RunningMonitor; public class VMListTableViewer extends AbstractTableViewer { private static final int BUTTON_WIDTH = 32; @@ -244,8 +243,8 @@ public class VMListTableViewer extends AbstractTableViewer { // reloading emulator list from data directory public void refreshVMPropertyList() { ProfileList.settingVMPropertyList(); - CheckingRunningEmulator.refreshVMPropertyList(); - RefreshWorker.refreshVMConnect(); + // refresh all VM state + RunningMonitor.refreshAll(); makeTableItem(); } diff --git a/src/org/tizen/emulator/manager/ui/widgets/VMButton.java b/src/org/tizen/emulator/manager/ui/widgets/VMButton.java index 44abc2b..1e602f8 100644 --- a/src/org/tizen/emulator/manager/ui/widgets/VMButton.java +++ b/src/org/tizen/emulator/manager/ui/widgets/VMButton.java @@ -67,7 +67,6 @@ import org.tizen.emulator.manager.vms.VMProperty; import org.tizen.emulator.manager.vms.VMProperty.FSImageType; import org.tizen.emulator.manager.vms.helper.CheckingRunningEmulator; import org.tizen.emulator.manager.vms.helper.HelperClass; -import org.tizen.emulator.manager.vms.helper.VMSocket; public class VMButton extends ImageButton { private VMButton button = null; @@ -448,13 +447,15 @@ public class VMButton extends ImageButton { if (prop != null) { if (CheckingRunningEmulator.isRemote(prop) && prop.isRunning()) { int webVMPort = 0; - synchronized (VMSocket.list) { - for (VMSocket s : VMSocket.list) { + /* FIXME + synchronized (ECSSocket.list) { + for (ECSSocket s : ECSSocket.list) { if (s.getProperty() != null && s.getProperty().getName().equals(prop.getName())) { webVMPort = s.getEcs_port() + 3; } } } + */ if (webVMPort > 0) { String ip = HelperClass.getLocalIPAddress(webVMPort-3); button.setToolTipText(prop.getName() + Messages.getString("VMButton.RemoteToolTip.0") + "\n" + //$NON-NLS-1$ //$NON-NLS-2$ diff --git a/src/org/tizen/emulator/manager/vms/EmulatorVMList.java b/src/org/tizen/emulator/manager/vms/EmulatorVMList.java index 016aa33..8999a58 100644 --- a/src/org/tizen/emulator/manager/vms/EmulatorVMList.java +++ b/src/org/tizen/emulator/manager/vms/EmulatorVMList.java @@ -35,7 +35,10 @@ import java.io.FileFilter; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import javax.xml.bind.JAXBContext; @@ -56,7 +59,8 @@ public class EmulatorVMList { static private JAXBContext context = null; static private String vmsConfigDirectory = ""; //$NON-NLS-1$ - private final List propertiesList = new ArrayList(); + private final List propertiesList = + Collections.synchronizedList(new ArrayList()); private final ObjectFactory objectFactory = new ObjectFactory(); static { @@ -90,7 +94,7 @@ public class EmulatorVMList { loadProperties(); } - public void loadProperties() { + private void loadProperties() { synchronized (propertiesList) { propertiesList.clear(); // traverse VMs... @@ -172,9 +176,22 @@ public class EmulatorVMList { return property; } } + } - return null; + return null; + } + + public VMProperty getProperty(Path childImagePath) { + synchronized (propertiesList) { + for (VMProperty property : propertiesList) { + Path path = Paths.get(property.getChildImagePath()); + if (path.equals(childImagePath)) { + return property; + } + } } + + return null; } public VMProperty[] getProperties() { diff --git a/src/org/tizen/emulator/manager/vms/VMLauncher.java b/src/org/tizen/emulator/manager/vms/VMLauncher.java index 1771a45..f80a133 100644 --- a/src/org/tizen/emulator/manager/vms/VMLauncher.java +++ b/src/org/tizen/emulator/manager/vms/VMLauncher.java @@ -44,11 +44,10 @@ import org.tizen.emulator.manager.resources.FilePathResources; import org.tizen.emulator.manager.resources.StringResources; import org.tizen.emulator.manager.tool.PortHelper; import org.tizen.emulator.manager.ui.dialog.MessageDialog; -import org.tizen.emulator.manager.vms.helper.CheckingRunningEmulator; -import org.tizen.emulator.manager.vms.helper.MonitoringEmulator; import org.tizen.emulator.manager.vms.helper.VMLauncherException; import org.tizen.emulator.manager.vms.helper.VMLogUtil; import org.tizen.emulator.manager.vms.helper.VMWorkerException; +import org.tizen.emulator.manager.vms.monitor.LaunchingMonitor; import org.tizen.emulator.manager.vms.option.LaunchConfig; import org.tizen.emulator.manager.vms.option.NetProxyOption; import org.tizen.emulator.manager.vms.option.OPTION_KEY; @@ -64,31 +63,22 @@ public class VMLauncher { List cmd = getCommand(property); - CheckingRunningEmulator.addEmulator(property); - MonitoringEmulator monitor = new MonitoringEmulator(property); String emulatorPath = property.getPropertyValue().baseImage.getPlatform().getEmulatorPath(); + Process process = launch(property.getName(), emulatorPath, cmd, path); - if (process != null) { - monitor.setProcess(process); - monitor.start(); - if (wait) { - try { - monitor.join(); - } catch (InterruptedException e) { - EMLogger.getLogger().warning(e.getMessage()); - } - if (monitor.isSuccess()) { - return true; - } else { - return false; - } - } - return true; - } else { - CheckingRunningEmulator.removeEmulator(property, false); - monitor.interrupt(); + if (process == null) { return false; } + + LaunchingMonitor monitor = new LaunchingMonitor(property, process); + + if (!wait) { + monitor.asyncExecute(8); // timeout : 8 seconds + + return true; + } + + return monitor.execute(); } private static void checkPortNumber() throws VMLauncherException { @@ -206,5 +196,4 @@ public class VMLauncher { return process; } - -} +} \ No newline at end of file diff --git a/src/org/tizen/emulator/manager/vms/VMProperty.java b/src/org/tizen/emulator/manager/vms/VMProperty.java index 9e7372a..6164230 100644 --- a/src/org/tizen/emulator/manager/vms/VMProperty.java +++ b/src/org/tizen/emulator/manager/vms/VMProperty.java @@ -37,6 +37,7 @@ import org.tizen.emulator.manager.plugin.EMPlugin; import org.tizen.emulator.manager.plugin.ExtensionItem; import org.tizen.emulator.manager.plugin.PluginStringResources; import org.tizen.emulator.manager.resources.FilePathResources; +import org.tizen.emulator.manager.vms.helper.CheckingRunningEmulator; import org.tizen.emulator.manager.vms.helper.VMLogUtil; import org.tizen.emulator.manager.vms.xml.EmulatorConfiguration; @@ -45,6 +46,15 @@ public class VMProperty { public static final int MIN_DPI = 100; public static final int MAX_DPI = 480; + public static enum State { + NOT_SET, + NOT_AVAILABLE, + BUSY, + READY, + LAUNCHING, + RUNNING, + } + private File propertyFile; private long lastModified; private VMPropertyConfiguration configuration; @@ -52,9 +62,7 @@ public class VMProperty { private VMWorkerCommon worker; private VMPropertyValue value = null; - private boolean isRunning = false; - // Is it possible to launch emulator or not? - private boolean isAvailable = true; + private State state = State.READY; private long lastLaunched; @@ -160,11 +168,68 @@ public class VMProperty { return worker; } + public State getState() { + return state; + } + + public synchronized boolean setState(State state) { + if (this.state == State.BUSY) { + // pending state change + return false; + } + + switch (state) { + case NOT_SET: + // can not enter here + assert true; + break; + case NOT_AVAILABLE: + break; + case BUSY: + assert this.state != State.RUNNING; + break; + case READY: + if (this.state == State.RUNNING) { + if (worker != null) { + worker.sendRemoteLog("stop"); //$NON-NLS-1$ + } + } + break; + case LAUNCHING: + assert this.state == State.READY; + break; + case RUNNING: + assert this.state == State.LAUNCHING || this.state == State.READY; + if (worker != null) { + worker.sendRemoteLog("start"); //$NON-NLS-1$ + } + break; + default: + break; + } + + this.state = state; + + CheckingRunningEmulator.notifyToStateListener(this); + + return true; + } + public boolean isRunning() { - return isRunning; + return this.state == State.RUNNING || this.state == State.LAUNCHING; } - public void setRunning(boolean isRunning) { - this.isRunning = isRunning; + + public boolean isAvailable() { + return this.state != State.NOT_AVAILABLE; + } + + // TODO: not tested yet + public void setAvailable(boolean isAvailable) { + if (isAvailable) { + setState(State.READY); + } else { + setState(State.NOT_AVAILABLE); + } } // for plug-in source -> need to delete @@ -249,14 +314,6 @@ public class VMProperty { return true; } - public boolean isAvailable() { - return isAvailable; - } - - public void setAvailable(boolean isAvailable) { - this.isAvailable = isAvailable; - } - public long getLastLaunchedTime() { return lastLaunched; } diff --git a/src/org/tizen/emulator/manager/vms/VMWorkerCommon.java b/src/org/tizen/emulator/manager/vms/VMWorkerCommon.java index 5ce9bd2..e6e21ad 100644 --- a/src/org/tizen/emulator/manager/vms/VMWorkerCommon.java +++ b/src/org/tizen/emulator/manager/vms/VMWorkerCommon.java @@ -44,7 +44,6 @@ import org.tizen.emulator.manager.Messages; import org.tizen.emulator.manager.logging.EMLogger; import org.tizen.emulator.manager.resources.FilePathResources; import org.tizen.emulator.manager.resources.StringResources; -import org.tizen.emulator.manager.vms.helper.CheckingRunningEmulator; import org.tizen.emulator.manager.vms.helper.QemuImgProc; import org.tizen.emulator.manager.vms.helper.VMLauncherException; import org.tizen.emulator.manager.vms.helper.VMWorkerException; @@ -128,7 +127,7 @@ public class VMWorkerCommon implements IVMWorker { throw new VMWorkerException(""); //$NON-NLS-1$ } else { // success to launch vm - property.setRunning(true); +// property.setRunning(true); property.setLastLaunchedTime(new Date().getTime()); } @@ -233,7 +232,8 @@ public class VMWorkerCommon implements IVMWorker { + (useCompress ? " using compress." : ".")); // block other function while to create base image - CheckingRunningEmulator.addEmulator(property); +// CheckingRunningEmulator.addEmulator(property); + property.setState(VMProperty.State.BUSY); } finally { // lock.release WorkerLock.release(); @@ -275,7 +275,8 @@ public class VMWorkerCommon implements IVMWorker { propertyLockFile.delete(); } - CheckingRunningEmulator.removeEmulator(property, false); +// CheckingRunningEmulator.removeEmulator(property, false); + property.setState(VMProperty.State.READY); EMLogger.getLogger().info("Success to create base image." + StringResources.NEW_LINE + "Base image path: " + baseImagePath); @@ -416,15 +417,7 @@ public class VMWorkerCommon implements IVMWorker { } // - if (CheckingRunningEmulator.isContains(property)) { - throw new VMWorkerException("[" + property.getName() //$NON-NLS-1$ - + Messages.getString("VMWorkerCommon.WorkingError.1")); //$NON-NLS-1$ - } - if (checking(property)) { - if (!EmulatorManager.isConsoleMode()) { - CheckingRunningEmulator.connectToECS(property); - } throw new VMWorkerException("[" + property.getName() //$NON-NLS-1$ + Messages.getString("VMWorkerCommon.WorkingError.1")); //$NON-NLS-1$ } else { diff --git a/src/org/tizen/emulator/manager/vms/helper/CheckingRunningEmulator.java b/src/org/tizen/emulator/manager/vms/helper/CheckingRunningEmulator.java index 0c38749..017ec2b 100644 --- a/src/org/tizen/emulator/manager/vms/helper/CheckingRunningEmulator.java +++ b/src/org/tizen/emulator/manager/vms/helper/CheckingRunningEmulator.java @@ -30,52 +30,17 @@ package org.tizen.emulator.manager.vms.helper; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.NoConnectionPendingException; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.nio.channels.SocketChannel; -import java.nio.charset.Charset; import java.util.ArrayList; -import java.util.Iterator; +import java.util.Collections; import java.util.List; -import org.eclipse.swt.widgets.Display; -import org.tizen.ecp.msg.genmsg.ecs.Ecs.DeviceAns; -import org.tizen.ecp.msg.genmsg.ecs.Ecs.Master; -import org.tizen.ecp.msg.genmsg.ecs.EcsIds.Master_Type; import org.tizen.emulator.manager.EmulatorManager; import org.tizen.emulator.manager.EmulatorManager.ManagerModeType; -import org.tizen.emulator.manager.Messages; -import org.tizen.emulator.manager.logging.EMLogger; -import org.tizen.emulator.manager.resources.StringResources; -import org.tizen.emulator.manager.ui.dialog.MessageDialog; -import org.tizen.emulator.manager.vms.EmulatorVMList; import org.tizen.emulator.manager.vms.VMProperty; -import org.tizen.emulator.manager.vms.VMWorkerCommon; -import org.tizen.emulator.manager.vms.helper.VMSocketQueue.QueueObject; -public class CheckingRunningEmulator { - private static ArrayList emList = new ArrayList (); - - private static CheckingThread thread = null; - - // Decide whether popup-message display or not. - private static List LAUNCHED_VM_LIST = new ArrayList(); - private static List listenerList = new ArrayList(); - - public static void addLaunchedVMList(String vmName) { - synchronized(LAUNCHED_VM_LIST) { - LAUNCHED_VM_LIST.add(vmName); - } - } - - private static void removeLaunchedVMList(String vmName) { - synchronized(LAUNCHED_VM_LIST) { - LAUNCHED_VM_LIST.remove(vmName); - } - } +public final class CheckingRunningEmulator { + private static List listenerList = + Collections.synchronizedList(new ArrayList()); public static void addRunningEmulatorListener(EmulatorStatusListener listener) { listenerList.add(listener); @@ -85,485 +50,13 @@ public class CheckingRunningEmulator { listenerList.remove(listener); } - public static boolean needPopupMessage(VMSocket vms) { - if (vms.getProperty() != null) { - String vmName = vms.getProperty().getName(); - String launched = null; - synchronized(LAUNCHED_VM_LIST) { - for (String s : LAUNCHED_VM_LIST) { - if (s.equals(vmName)) { - launched = s; - } - } - if (launched != null) { - removeLaunchedVMList(launched); - return true; - } - } - } - return false; - - } - - public static synchronized void startCheckingThread() { - if (EmulatorManager.isConsoleMode()) { - return; - } - - if (thread != null && thread.isAlive()) { - return; - } - - thread = new CheckingThread(); - thread.setName("checkEM"); //$NON-NLS-1$ - thread.setDaemon(true); - thread.start(); - } - - public static Selector getSelector() { - if (thread != null) { - return thread.getSelector(); - } - return null; - } - - - public static boolean addToRegisterQueue(VMSocket vmSocket, int ops){ - if (thread != null) { - return thread.addToRegisterQueue(vmSocket, ops); - } - return false; - } - - public static void addEmulator(VMProperty prop) { - synchronized (emList) { - if(!emList.contains(prop.getName())) { - emList.add(prop.getName()); - } - } - - setRunning(prop.getName(), true); - } - - public static void removeEmulator(VMProperty prop, boolean isSuccess) { - synchronized (emList) { - emList.remove(prop.getName()); - } - if (!isSuccess) { - setRunning(prop.getName(), false); - } else { - addLaunchedVMList(prop.getName()); - boolean checkFinished; - boolean isRunning = false; - int count=1; - VMSocket.ResultType res; - do { - res = connectToECS(prop); - EMLogger.getLogger().info("Try connection #" + count + ", result: "+ res); //$NON-NLS-1$ //$NON-NLS-2$ - - switch (res) { - case ECS_NOT_READY: - case IMAGEPATH_NOT_READY: - checkFinished = false; - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - EMLogger.getLogger().warning(e.getMessage()); - } - break; - - case LAUNCHED_VM_DETECTED: - isRunning = true; - checkFinished = true; - break; - - case SOCK_CLOSED: - default: - checkFinished = true; - } - - } while (!checkFinished && count++ < 10); - - if (isRunning) { - VMWorkerCommon worker = prop.getWorker(); - if (worker != null) { - worker.sendRemoteLog("start"); //$NON-NLS-1$ - } - - } else { - setRunning(prop, false); - EMLogger.getLogger().info("No response from VM (" + prop.getName() + ")."); //$NON-NLS-1$ //$NON-NLS-2$ - } - } - } - - // for to remove property after success connected ecs - private static void removeEmulator(VMProperty prop) { - synchronized (emList) { - emList.remove(prop.getName()); - } - } - - public static boolean isContains(String name) { - synchronized (emList) { - return emList.contains(name); - } - } - - public static boolean isContains(VMProperty prop) { - synchronized (emList) { - return emList.contains(prop.getName()); - } - } - - public static VMSocket.ResultType connectToECS(VMProperty vm) { - - VMSocket.ResultType result = VMSocket.ResultType.SOCK_CLOSED; - if(EmulatorManager.isConsoleMode()){ - return result; - } - boolean isHeartBeat = false; - boolean isVMFound = false; - boolean isEcsNotReady = false; - boolean isImagepathNotReady = false; - VMSocket currentVms = null; - - synchronized (VMSocket.list) { - for (VMSocket s : VMSocket.list) { - boolean needCheck = false; - if (s.getSocket() == null || !s.getSocket().isConnected()) { - needCheck = s.sendMessage(); - - } else if (s.getSocket().isConnected()) { - if (s.getProperty() != null && vm.getName().equals(s.getProperty().getName())) { - EMLogger.getLogger().info("Socket already connected.. :" + s.getProperty().getName()); //$NON-NLS-1$ - s.disconnect(); - // Send request one more time. - needCheck = s.sendMessage(); - } - } - if(needCheck){ - VMSocket.ResultType type = s.checkReceiveMessage(vm); - - switch(type){ - case LAUNCHED_VM_DETECTED: - isVMFound = true; - currentVms = s; - break; - - case IMAGEPATH_NOT_READY: - isImagepathNotReady = true; - break; - - case SOCK_CLOSED: - break; - - case HEARTBEAT: - isHeartBeat = true; - break; - default: - // TODO - break; - } - - if(isVMFound) - break; - - } else { - isEcsNotReady = true; - } - } - } - - if (isVMFound) { - setRunning(vm, true); - CheckingRunningEmulator.removeEmulator(vm); - result = VMSocket.ResultType.LAUNCHED_VM_DETECTED; - // Check remote option. - if (isRemote(vm)) { -// runServer(currentVms); - showInfoDialog(currentVms); - } - - } else if (isImagepathNotReady) { - result = VMSocket.ResultType.IMAGEPATH_NOT_READY; - - } else if (isEcsNotReady){ - result = VMSocket.ResultType.ECS_NOT_READY; - } - - if (!isHeartBeat){ - // TODO - } - - return result; - } - - public static void setRunning(String vmName, boolean isRunning) { - VMProperty prop = EmulatorVMList.getInstance().getProperty(vmName); - setRunning(prop, isRunning); - } - - public static void setRunning(VMProperty prop, boolean isRunning) { - if (prop == null) { - return; - } - - prop.setRunning(isRunning); - + public static void notifyToStateListener(VMProperty property) { for (EmulatorStatusListener listener : listenerList ) { - listener.changeEmulatorRunningStatus(prop); - } - } - - public static void refreshVMPropertyList() { - for (VMProperty prop : (EmulatorVMList.getInstance().getProperties())) { - if (emList.contains(prop.getName())) { - prop.setRunning(true); - } - } - - for (VMSocket s : VMSocket.list){ - if (s.getProperty() != null) { - for (VMProperty prop : (EmulatorVMList.getInstance().getProperties())) { - if (prop.getName().equals(s.getProperty().getName())) { - s.setProperty(prop); - prop.setRunning(true); - break; - } - } - } - } - } - - public static class CheckingThread extends Thread { - private Selector selector = null; - - private final VMSocketQueue registeringQueue = new VMSocketQueue(); - - private void init() { - try { - selector = Selector.open(); - } catch (IOException e) { - EMLogger.getLogger().warning(e.getMessage()); - selector = null; - } - } - - public Selector getSelector() { - if (selector == null) { - init(); - } - return selector; - } - - - public boolean addToRegisterQueue(VMSocket vmSocket, int ops){ - if (getSelector() != null) { - registeringQueue.add(vmSocket, ops); - selector.wakeup(); - return true; - } - return false; - } - - // register socket to selector - public void registerSocket() { - while(true) { - QueueObject queueObject = registeringQueue.poll(); - if(queueObject == null) { - return; - } - - VMSocket vmSocket = queueObject.getVmSocket(); - int ops = queueObject.getOps(); - if (selector != null) { - SocketChannel sc = vmSocket.getSocket(); - try { - sc.configureBlocking(false); - sc.register(selector, ops, vmSocket); - } catch (Exception e) { - EMLogger.getLogger().warning(e.getMessage()); - disconnect(vmSocket); - } - } else { - disconnect(vmSocket); - } - } - } - - @Override - public void run() { - - for (VMSocket s : VMSocket.list) { - if (s.getSocket() == null || !s.getSocket().isConnected()) { - s.connect(); - } - } - - while (true) { - if (getSelector () != null) { - try { - selector.select(); - registerSocket(); - Iterator it = selector.selectedKeys().iterator(); - while(it.hasNext()) { - SelectionKey key = it.next(); - if (key.isReadable()) { - readBuffer(key); - } else if (key.isConnectable()) { - checkConnection(key); - } - it.remove(); - } - } catch (IOException e) { - EMLogger.getLogger().warning("Selector exception: " + e.getMessage()); //$NON-NLS-1$ - - } catch (Exception e) { - EMLogger.getLogger().warning(e.getClass().getName() + " : " + e.getMessage()); //$NON-NLS-1$ - } - } - } - } - - private final ByteBuffer length = ByteBuffer.allocate(4); - private final ByteBuffer buffer = ByteBuffer.allocate(4096); - private int size = 0; - private void readBuffer(SelectionKey key) { - SocketChannel sc = (SocketChannel)key.channel(); - VMSocket vms = (VMSocket)key.attachment(); - length.clear(); - buffer.clear(); - try { - size = sc.read(length); - if (size == -1) { - setVMExit(vms); - return; - } - - length.position(0); - int len = length.getInt(); - buffer.limit(len); - size = sc.read(buffer); - if (size == -1) { - setVMExit(vms); - return; - } - - buffer.flip(); - buffer.position(0); - byte[] buff = new byte[len]; - buffer.get(buff); - Master msg = Master.parseFrom(buff); - if (msg.getType() == Master_Type.DEVICE_ANS) { - DeviceAns ans = msg.getDeviceAns(); - if (ans.getCategory().equals("info")) { //$NON-NLS-1$ - String path = new String(ans.getData().toByteArray(), - Charset.forName(System.getProperty("file.encoding"))); - EMLogger.getLogger().info("ecs response : " + path); - settingProperty(path, vms); - } - } else if (msg.getType() == Master_Type.KEEPALIVE_REQ) { - if (vms != null) { - vms.sendKeepAliveAns(); - } - } - } catch (IOException e){ - EMLogger.getLogger().warning(e.getMessage()); - setVMExit(vms); - } catch (IllegalArgumentException e) { - EMLogger.getLogger().warning(e.getMessage()); - if (length != null) { - EMLogger.getLogger().warning("Socket Msg length : " + length.getInt()); //$NON-NLS-1$ - } - } - } - - private void checkConnection(SelectionKey key) { - SocketChannel sc = (SocketChannel)key.channel(); - VMSocket vms = (VMSocket)key.attachment(); - boolean isReady = false; - - if (sc.isConnected()) { - isReady = addToRegisterQueue(vms, SelectionKey.OP_READ); - } else { - try { - if (sc.finishConnect()) { - // Connect success - isReady = addToRegisterQueue(vms, SelectionKey.OP_READ); - } else { - // Connect pending. - EMLogger.getLogger().info("Connection not completed yet : " + vms.getEcs_port()); //$NON-NLS-1$ - return; - } - } catch (NoConnectionPendingException e) { - EMLogger.getLogger().warning("finishConnect error. " + e.getClass().getName() + " : " + e.getMessage()); - vms.reconnect(); - return; - - } catch (IOException e) { // Connection failed. - isReady = false; - } catch (Exception e) { - EMLogger.getLogger().warning(e.getClass().getName() + " : " + e.getMessage()); //$NON-NLS-1$ - } - } - - if (isReady) { - vms.sendDeviceReq(); - - } else { - // EMLogger.getLogger().info("Connection fail : " + vms.getEcs_port()); - vms.disconnect(); - } - } - - private static void setVMExit(VMSocket vms) { - if (vms.getProperty() != null) { - VMWorkerCommon worker = vms.getProperty().getWorker(); - if (worker != null) { - worker.sendRemoteLog("stop"); //$NON-NLS-1$ - } - } - disconnect(vms); - } - - public static void disconnect(VMSocket vms) { - // disconnect - if (vms != null) { - if (vms.getProperty() != null) { - CheckingRunningEmulator.setRunning(vms.getProperty(), false); - } - vms.disconnect(); - } - } - - private void settingProperty(String path, VMSocket vms) { - if (vms != null) { - RefreshWorker.addToFinishedSet(vms.getEcs_port()); - } - - for (VMProperty prop : (EmulatorVMList.getInstance().getProperties())) { - if (HelperClass.pathEquals(path, prop.getChildImagePath())) { - if (vms != null) { - vms.setProperty(prop); - RefreshWorker.addToFinishedSet(vms.getEcs_port()); - } - CheckingRunningEmulator.setRunning(prop, true); - CheckingRunningEmulator.removeEmulator(prop); - - // Check remote option. - if (isRemote(prop)) { -// runServer(vms); - showInfoDialog(vms); - } - - break; - } - } + listener.changeEmulatorRunningStatus(property); } - } + // FIXME public static String OPTION_VIEWER = "viewer"; //$NON-NLS-1$ public static String OPTION_TYPE = "type"; //$NON-NLS-1$ public static String VAL_WEB = "Web"; //$NON-NLS-1$ @@ -576,51 +69,4 @@ public class CheckingRunningEmulator { } return false; } - - /* - public static void runServer(VMSocket vms) { - // Run web(Node) server (if not running) - boolean nodeResult = WebEmulator.runWebServer(); - - // Run emulator(spice) server (if not running) - boolean spiceResult = WebEmulator.runEmulatorServer(vms); - - showInfoDialog(nodeResult, spiceResult, vms); - } - */ - - public static void showInfoDialog(VMSocket vms) { - if(needPopupMessage(vms)) { - final int clientPort = vms.getEcs_port() + 3; - final String vmName = (vms.getProperty() != null) ? vms.getProperty().getName() : ""; //$NON-NLS-1$ - final String ip = HelperClass.getLocalIPAddress(vms.getEcs_port()); - final String msg = "URL : http://" + ip + ":8080" + //$NON-NLS-1$ //$NON-NLS-2$ - StringResources.NEW_LINE - + "VM Port : " + clientPort + //$NON-NLS-1$ - StringResources.NEW_LINE + StringResources.NEW_LINE - + Messages.getString("CheckingRunningEmulator.WebViewerInfo.1"); //$NON-NLS-1$ - if (EmulatorManager.isConsoleMode()) { - System.out.println(msg); - } else { - Display.getDefault().asyncExec(new Runnable() { - @Override - public void run() { - MessageDialog msgDialog = new MessageDialog(); - String title = Messages.getString("CheckingRunningEmulator.WebViewerInfo.2") + vmName + ")"; //$NON-NLS-1$ //$NON-NLS-2$ - msgDialog.openInfoDialog(title, StringResources.NEW_LINE + msg); - } - }); - } - } - } - - /* - public static void killServer(VMSocket vms) { - WebEmulator.killEmulatorServer(vms); - - // Kill web server if no remote VM runs. - WebEmulator.killWebServer(); - } - */ - } diff --git a/src/org/tizen/emulator/manager/vms/helper/RefreshWorker.java b/src/org/tizen/emulator/manager/vms/helper/RefreshWorker.java deleted file mode 100644 index ed24c98..0000000 --- a/src/org/tizen/emulator/manager/vms/helper/RefreshWorker.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Emulator Manager - * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: - * Minkee Lee - * MunKyu Im - * SeokYeon Hwang - * JiHye Kim - * YeongKyoon Lee - * - * This program 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. - * - * This program 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. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributors: - * - S-Core Co., Ltd - * - */ - -package org.tizen.emulator.manager.vms.helper; - -import java.util.HashSet; -import java.util.Set; - -import org.tizen.emulator.manager.logging.EMLogger; -import org.tizen.emulator.manager.vms.EmulatorVMList; -import org.tizen.emulator.manager.vms.VMProperty; - -public class RefreshWorker { - - private static Set finishedSet = new HashSet(); - - public static void addToFinishedSet(int port) { - synchronized (finishedSet) { - finishedSet.add(port); - } - } - - public static void clearFinishedSet() { - synchronized (finishedSet) { - finishedSet.clear(); - } - } - - public static void refreshVMConnect() { - - // Re-connect VMs - synchronized (VMSocket.list) { - for (VMSocket s : VMSocket.list) { - s.disconnect(); - } - clearFinishedSet(); - for (VMSocket s : VMSocket.list) { - s.connect(); - } - } - - // Wait until all re-connect ended. - while (true) { - synchronized (finishedSet) { - if (finishedSet.size() == VMSocket.MAX_CONNECT_NUM) { - break; - } - } - - try { - Thread.sleep(100); - } catch (InterruptedException e) { - EMLogger.getLogger().warning(e.getMessage()); - } - } - EMLogger.getLogger().info("Refresh complete"); //$NON-NLS-1$ - - // Change VMs' running state - for (VMProperty prop : (EmulatorVMList.getInstance().getProperties())) { - if (VMSocket.isPropertyInList(prop)) { - prop.setRunning(true); - } else { - prop.setRunning(false); - } - } - } -} \ No newline at end of file diff --git a/src/org/tizen/emulator/manager/vms/helper/VMSocketQueue.java b/src/org/tizen/emulator/manager/vms/helper/VMSocketQueue.java deleted file mode 100644 index c4fc637..0000000 --- a/src/org/tizen/emulator/manager/vms/helper/VMSocketQueue.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Emulator Manager - * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: - * Minkee Lee - * SeokYeon Hwang - * YeongKyoon Lee - * - * This program 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. - * - * This program 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. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributors: - * - S-Core Co., Ltd - * - */ - -package org.tizen.emulator.manager.vms.helper; - -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - - -public class VMSocketQueue { - - public static class QueueObject { - VMSocket vmSocket; - int ops; // select-event type - - public QueueObject(VMSocket vmSocket, int ops){ - this.vmSocket = vmSocket; - this.ops = ops; - } - - public VMSocket getVmSocket() { - return vmSocket; - } - public void setVmSocket(VMSocket vmSocket) { - this.vmSocket = vmSocket; - } - public int getOps() { - return ops; - } - public void setOps(int ops) { - this.ops = ops; - } - } - - private BlockingQueue queue ; - - public VMSocketQueue() { - queue = new LinkedBlockingQueue(); - } - - public boolean add(VMSocket vmSocket, int ops) { - return queue.add(new QueueObject(vmSocket, ops)); - } - - public QueueObject poll() { - return queue.poll(); - } -} diff --git a/src/org/tizen/emulator/manager/vms/monitor/ECSMonitor.java b/src/org/tizen/emulator/manager/vms/monitor/ECSMonitor.java new file mode 100644 index 0000000..229d353 --- /dev/null +++ b/src/org/tizen/emulator/manager/vms/monitor/ECSMonitor.java @@ -0,0 +1,216 @@ +/* + * Emulator Manager + * + * Copyright (C) 2011 - 2016 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * JiHye Kim + * Minkee Lee + * + * This program 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. + * + * This program 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +package org.tizen.emulator.manager.vms.monitor; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.SocketChannel; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +import org.tizen.ecp.msg.genmsg.ecs.Ecs.DeviceAns; +import org.tizen.ecp.msg.genmsg.ecs.Ecs.Master; +import org.tizen.ecp.msg.genmsg.ecs.EcsIds.Master_Type; +import org.tizen.emulator.manager.logging.EMLogger; +import org.tizen.emulator.manager.vms.monitor.VMSocketQueue.QueueObject; + +final class ECSMonitor extends RunningMonitor { + private final VMSocketQueue registeringQueue = new VMSocketQueue(); + private final Selector selector; + + private List sockets = new ArrayList(); + + ECSMonitor() throws IOException { + selector = Selector.open(); + + for (int i = 26103; i < 26194; i += 10) { + sockets.add(new ECSSocket(i)); + } + + new MonitoringThread(new ConnetionMonitor(), "ECSConnectionMonitor").start(); + new MonitoringThread(new SocketMonitor(), "ECSSocketMonitor").start(); + } + + private void addToRegisterQueue(ECSSocket socket, int ops){ + registeringQueue.add(socket, ops); + selector.wakeup(); + } + + final class ConnetionMonitor implements Runnable { + @Override + public void run() { + while(true) { + for (ECSSocket s : sockets) { + if (s.getSocket() != null && s.getSocket().isConnected()) { + continue; + } + + if (s.getSocket() == null && !s.tryConnect()) { + continue; + } + + addToRegisterQueue(s, SelectionKey.OP_READ); + } + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + + final class SocketMonitor implements Runnable { + // register socket to selector + private void registerSocket() { + while(true) { + QueueObject queueObject = registeringQueue.poll(); + if(queueObject == null) { + return; + } + + ECSSocket socket = queueObject.socket; + SocketChannel sc = socket.getSocket(); + + try { + sc.register(selector, queueObject.ops, socket); + } catch (Exception e) { + EMLogger.getLogger().warning(e.getMessage()); + disconnect(socket); + } + + socket.sendDeviceReq(); + } + } + + private void runningVMDetected(String path, ECSSocket vms) { + Path vmPath = Paths.get(path); + vms.setPath(vmPath); + + updateState(vmPath, true); + } + + private final ByteBuffer length = ByteBuffer.allocate(4); + private final ByteBuffer buffer = ByteBuffer.allocate(4096); + private int size = 0; + private void readBuffer(SelectionKey key) { + SocketChannel sc = (SocketChannel)key.channel(); + ECSSocket vms = (ECSSocket)key.attachment(); + + if (vms == null) { + // FIXME + return; + } + + length.clear(); + buffer.clear(); + try { + size = sc.read(length); + if (size == -1) { + disconnect(vms); + return; + } + + length.position(0); + int len = length.getInt(); + buffer.limit(len); + size = sc.read(buffer); + if (size == -1) { + disconnect(vms); + return; + } + + buffer.flip(); + buffer.position(0); + byte[] buff = new byte[len]; + buffer.get(buff); + Master msg = Master.parseFrom(buff); + if (msg.getType() == Master_Type.DEVICE_ANS) { + DeviceAns ans = msg.getDeviceAns(); + if (ans.getCategory().equals("info")) { //$NON-NLS-1$ + String path = new String(ans.getData().toByteArray(), + Charset.forName(System.getProperty("file.encoding"))); + EMLogger.getLogger().info("ecs response : " + path); + + runningVMDetected(path, vms); + } + } else if (msg.getType() == Master_Type.KEEPALIVE_REQ) { + vms.sendKeepAliveAns(); + } + } catch (IOException e){ + EMLogger.getLogger().warning(e.getMessage()); + disconnect(vms); + } catch (IllegalArgumentException e) { + EMLogger.getLogger().warning(e.getMessage()); + if (length != null) { + EMLogger.getLogger().warning("Socket Msg length : " + length.getInt()); //$NON-NLS-1$ + } + } + } + + private void disconnect(ECSSocket vms) { + vms.disconnect(); + + updateState(vms.getPath(), false); + } + + @Override + public void run() { + while (true) { + try { + selector.select(); + registerSocket(); + for (SelectionKey key : selector.selectedKeys()) { + if (key.isReadable()) { + readBuffer(key); + } else { + ECSSocket vms = (ECSSocket)key.attachment(); + if (vms != null) { + disconnect(vms); + } + } + } + } catch (IOException e) { + EMLogger.getLogger().warning("Selector exception: " + e.getMessage()); //$NON-NLS-1$ + + } catch (Exception e) { + EMLogger.getLogger().warning(e.getClass().getName() + " : " + e.getMessage()); //$NON-NLS-1$ + } + } + } + } +} + diff --git a/src/org/tizen/emulator/manager/vms/helper/VMSocket.java b/src/org/tizen/emulator/manager/vms/monitor/ECSSocket.java similarity index 53% rename from src/org/tizen/emulator/manager/vms/helper/VMSocket.java rename to src/org/tizen/emulator/manager/vms/monitor/ECSSocket.java index ecf9d8b..bda437e 100644 --- a/src/org/tizen/emulator/manager/vms/helper/VMSocket.java +++ b/src/org/tizen/emulator/manager/vms/monitor/ECSSocket.java @@ -1,7 +1,7 @@ /* * Emulator Manager * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2016 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: * Minkee Lee @@ -29,17 +29,16 @@ */ -package org.tizen.emulator.manager.vms.helper; +package org.tizen.emulator.manager.vms.monitor; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; -import java.nio.channels.SelectionKey; import java.nio.channels.SocketChannel; -import java.nio.charset.Charset; -import java.util.ArrayList; +import java.nio.file.Path; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; -import org.tizen.ecp.msg.genmsg.ecs.Ecs.DeviceAns; import org.tizen.ecp.msg.genmsg.ecs.Ecs.DeviceReq; import org.tizen.ecp.msg.genmsg.ecs.Ecs.KeepAliveAns; import org.tizen.ecp.msg.genmsg.ecs.Ecs.Master; @@ -47,34 +46,19 @@ import org.tizen.ecp.msg.genmsg.ecs.EcsIds.Master_Type; import org.tizen.emulator.manager.logging.EMLogger; import org.tizen.emulator.manager.vms.VMProperty; -public class VMSocket { +final class ECSSocket { + private Path imagePath; - public enum ResultType { + enum ResultType { LAUNCHED_VM_DETECTED, ECS_NOT_READY, IMAGEPATH_NOT_READY, SOCK_CLOSED, HEARTBEAT; } public static int MAX_CONNECT_NUM = 10; - public static ArrayList list = new ArrayList(); - static { - for (int i = 26103; i < 26194; i += MAX_CONNECT_NUM) { - list.add(new VMSocket(i)); - } - } - - public static boolean isPropertyInList(VMProperty param) { - for (VMSocket s : list) { - if (param.equals(s.getProperty())) { - return true; - } - } - return false; - } - private final int ecs_port; private SocketChannel socket; private VMProperty property; - private VMSocket(int port) { + ECSSocket(int port) { this.ecs_port = port; } @@ -82,12 +66,16 @@ public class VMSocket { return ecs_port; } - public SocketChannel getSocket() { - return socket; + void setPath(Path path) { + this.imagePath = path; } - public void setSocket(SocketChannel socket) { - this.socket = socket; + Path getPath() { + return imagePath; + } + + public SocketChannel getSocket() { + return socket; } public VMProperty getProperty() { @@ -98,115 +86,18 @@ public class VMSocket { this.property = property; } - public boolean connect() { - // Add socket to selector and try connect. - // Connection process is completed by selector event. - try { - socket = SocketChannel.open(); - socket.configureBlocking(false); - - if (CheckingRunningEmulator.addToRegisterQueue(this, SelectionKey.OP_CONNECT)) { - socket.connect(new InetSocketAddress("localhost", ecs_port)); //$NON-NLS-1$ - - } else { - EMLogger.getLogger().warning("Add to selector(connect event) fail :" + ecs_port); //$NON-NLS-1$ - disconnect(); - } - - } catch (IOException e) { - // EMLogger.getLogger().info("Connect fail.(" + e.getMessage() + ") - " + ecs_port); - disconnect(); - return false; - - } catch (Exception e) { - EMLogger.getLogger().warning(e.getClass().getName() + " : " + e.getMessage()); //$NON-NLS-1$ - return false; - } - - return true; - } - - - public boolean sendMessage(){ - // socket open + public boolean tryConnect() { try { socket = SocketChannel.open (new InetSocketAddress("localhost", ecs_port)); //$NON-NLS-1$ + socket.configureBlocking(false); } catch (IOException e) { // EMLogger.getLogger().warning("Connect to ECS(port:" + ecs_port + ") Fail. " + e.getMessage()); disconnect(); return false; } - if (socket == null) { - return false; - } - // send message - sendDeviceReq(); return true; - - } - - - public ResultType checkReceiveMessage(VMProperty vm){ - - if( socket != null){ - ByteBuffer length = ByteBuffer.allocate(4); - ByteBuffer buffer = ByteBuffer.allocate(4096); - String path = null; - - try { - int size = socket.read(length); - if (size == -1) { - disconnect(); - return ResultType.SOCK_CLOSED; - } - - length.position(0); - int len = length.getInt(); - buffer.limit(len); - size = socket.read(buffer); - if (size == -1) { - disconnect(); - return ResultType.SOCK_CLOSED; - } - - buffer.flip(); - buffer.position(0); - byte[] buff = new byte[len]; - buffer.get(buff); - Master msg = Master.parseFrom(buff); - if (msg.getType() == Master_Type.DEVICE_ANS) { - DeviceAns ans = msg.getDeviceAns(); - if (ans.getCategory().equals("info")) { //$NON-NLS-1$ - path = new String(ans.getData().toByteArray(), - Charset.forName(System.getProperty("file.encoding"))); - EMLogger.getLogger().info("ecs response : " + path); - if (HelperClass.pathEquals(path, vm.getChildImagePath())) { - setProperty(vm); - if (CheckingRunningEmulator.addToRegisterQueue(this, SelectionKey.OP_READ)) { - return ResultType.LAUNCHED_VM_DETECTED; - } - } else if (path.isEmpty()){ - EMLogger.getLogger().info("Path from ecs is not initialized yet. VM : " + vm.getName()); //$NON-NLS-1$ - return ResultType.IMAGEPATH_NOT_READY; - } - } - - } else if (msg.getType() == Master_Type.KEEPALIVE_REQ) { - if (CheckingRunningEmulator.addToRegisterQueue(this, SelectionKey.OP_READ)) { - sendKeepAliveAns(); - return ResultType.HEARTBEAT; - } - } - } catch (IOException e){ - disconnect(); - EMLogger.getLogger().warning(e.getMessage()); - } - } - - disconnect(); - return ResultType.SOCK_CLOSED; } public void disconnect() { @@ -216,10 +107,9 @@ public class VMSocket { } catch (IOException e) { EMLogger.getLogger().info(e.getMessage()); } - setSocket(null); + socket = null; } - setProperty(null); - RefreshWorker.addToFinishedSet(ecs_port); + property = null; } public void reconnect() { @@ -230,12 +120,12 @@ public class VMSocket { } catch (IOException e) { EMLogger.getLogger().info(e.getMessage()); } - setSocket(null); + socket = null; } - setProperty(null); + property = null; // connect again. - connect(); + tryConnect(); } @@ -303,3 +193,29 @@ public class VMSocket { } } + +final class VMSocketQueue { + public static class QueueObject { + final ECSSocket socket; + final int ops; // select-event type + + public QueueObject(ECSSocket socket, int ops){ + this.socket = socket; + this.ops = ops; + } + } + + private BlockingQueue queue; + + public VMSocketQueue() { + queue = new LinkedBlockingQueue(); + } + + public boolean add(ECSSocket socket, int ops) { + return queue.add(new QueueObject(socket, ops)); + } + + public QueueObject poll() { + return queue.poll(); + } +} \ No newline at end of file diff --git a/src/org/tizen/emulator/manager/vms/helper/MonitoringEmulator.java b/src/org/tizen/emulator/manager/vms/monitor/LaunchingMonitor.java similarity index 68% rename from src/org/tizen/emulator/manager/vms/helper/MonitoringEmulator.java rename to src/org/tizen/emulator/manager/vms/monitor/LaunchingMonitor.java index b080ee0..cbfdb8a 100644 --- a/src/org/tizen/emulator/manager/vms/helper/MonitoringEmulator.java +++ b/src/org/tizen/emulator/manager/vms/monitor/LaunchingMonitor.java @@ -1,7 +1,7 @@ /* * Emulator Manager * - * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2016 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: * JiHye Kim @@ -27,7 +27,7 @@ * */ -package org.tizen.emulator.manager.vms.helper; +package org.tizen.emulator.manager.vms.monitor; import java.io.BufferedReader; import java.io.IOException; @@ -43,53 +43,36 @@ import org.tizen.emulator.manager.resources.StringResources; import org.tizen.emulator.manager.ui.dialog.MessageDialog; import org.tizen.emulator.manager.vms.VMProperty; -public class MonitoringEmulator extends Thread { - private VMProperty property; - private Process process; - private int count = 8; +public final class LaunchingMonitor implements Runnable { + private final VMProperty property; + private final Process process; + private Output stdOut = null; + private Output stdErr = null; - public MonitoringEmulator(VMProperty property) { + public LaunchingMonitor(VMProperty property, Process process) { this.property = property; - this.setDaemon(true); - } - - public void setProcess(Process process) { - this.process = process; - } - - public void setProcess(Process process, int count) { this.process = process; - this.count = count; } - private StdOut stdOut = null; - private StdOut stdErr = null; - private boolean success = true; - - @Override - public void run() { + public boolean execute() { if (process == null || property == null) { - return; + return false; } - InputStreamReader in1 = new InputStreamReader(process.getInputStream()); - InputStreamReader in2 = new InputStreamReader(process.getErrorStream()); - BufferedReader readerOut = new BufferedReader(in1); - BufferedReader readerError = new BufferedReader(in2); + boolean success = true; + + BufferedReader readerOut = new BufferedReader(new InputStreamReader(process.getInputStream())); + BufferedReader readerError = new BufferedReader(new InputStreamReader(process.getErrorStream())); - stdOut = new StdOut(readerOut, property.getName()); - stdErr = new StdOut(readerError, property.getName()); + stdOut = new Output(readerOut, property.getName()); + Thread t1 = new Thread(stdOut, property.getName() + "STDOUT"); //$NON-NLS-1$ + + stdErr = new Output(readerError, property.getName()); + Thread t2 = new Thread(stdErr, property.getName() + "STDERR"); //$NON-NLS-1$ - Thread t1 = new Thread(stdOut); - Thread t2 = new Thread(stdErr); - t1.setName(property.getName() + "STDOUT"); //$NON-NLS-1$ - t2.setName(property.getName() + "STDERR"); //$NON-NLS-1$ t1.start(); t2.start(); - // start timer - new Thread(new Timer(this, count)).start(); - try { int exitValue = process.waitFor(); @@ -101,7 +84,7 @@ public class MonitoringEmulator extends Thread { stdErr.printMessageList(); if (exitValue != 0) { - setSuccess(false); + success = false; EMLogger.getLogger().warning( "You can see more information in the emulator-manager.log or " //$NON-NLS-1$ + property.getName() + "'s logs directory."); //$NON-NLS-1$ @@ -125,20 +108,18 @@ public class MonitoringEmulator extends Thread { } } } catch (InterruptedException e) { + // launched successfully EMLogger.getLogger().log(Level.FINE, e.getMessage()); } - CheckingRunningEmulator.removeEmulator(property, isSuccess()); + stdOut.setDone(); + stdErr.setDone(); try { t1.join(); - } catch (InterruptedException e1) { - EMLogger.getLogger().warning(e1.getMessage()); - } - try { t2.join(); - } catch (InterruptedException e1) { - EMLogger.getLogger().warning(e1.getMessage()); + } catch (InterruptedException e) { + EMLogger.getLogger().warning(e.getMessage()); } // close @@ -152,61 +133,47 @@ public class MonitoringEmulator extends Thread { } catch (IOException e) { EMLogger.getLogger().warning(e.getMessage()); } - } - public boolean isSuccess() { return success; } - public void setSuccess(boolean success) { - this.success = success; - } - -} - -class Timer implements Runnable { - private MonitoringEmulator monitor; - private int count; - - public Timer(MonitoringEmulator m) { - this(m, 8); - } - - public Timer(MonitoringEmulator m, int c) { - monitor = m; - count = c; + public void asyncExecute(int timeoutSec) { + new MonitoringThread(this, "LunchingMonitor", timeoutSec).start(); } @Override public void run() { - synchronized (this) { - try { - this.wait(1000 * count); - } catch (InterruptedException e) { - EMLogger.getLogger().warning(e.getMessage()); - } - } - - monitor.interrupt(); + property.setState(VMProperty.State.LAUNCHING); + if (!execute()) { + property.setState(VMProperty.State.READY); + } } } -class StdOut implements Runnable { +final class Output implements Runnable { private BufferedReader reader; private String vmName; private final ArrayList list = new ArrayList(); - public StdOut(BufferedReader reader, String name) { + private boolean isDone = false; + private boolean error = false; + + + Output(BufferedReader reader, String name) { this.reader = reader; this.vmName = name; } - public StdOut(InputStreamReader in, String name) { + Output(InputStreamReader in, String name) { this.reader = new BufferedReader(in); this.vmName = name; } + void setDone() { + this.isDone = true; + } + @Override public void run() { String msg = ""; //$NON-NLS-1$ @@ -242,7 +209,7 @@ class StdOut implements Runnable { e.printStackTrace(); } } - } while (CheckingRunningEmulator.isContains(vmName)); + } while (!isDone); } catch (IOException e) { EMLogger.getLogger().info(e.getMessage()); } finally { @@ -264,9 +231,7 @@ class StdOut implements Runnable { } } - private boolean error = false; - public void printMessageList() { error = true; } -} +} \ No newline at end of file diff --git a/src/org/tizen/emulator/manager/vms/monitor/LockFileMonitor.java b/src/org/tizen/emulator/manager/vms/monitor/LockFileMonitor.java new file mode 100644 index 0000000..1290ab9 --- /dev/null +++ b/src/org/tizen/emulator/manager/vms/monitor/LockFileMonitor.java @@ -0,0 +1,177 @@ +/* + * Emulator Manager + * + * Copyright (C) 2011 - 2016 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * JiHye Kim + * Minkee Lee + * + * This program 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. + * + * This program 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +package org.tizen.emulator.manager.vms.monitor; + +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.FileSystems; +import java.nio.file.FileVisitOption; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.StandardWatchEventKinds; +import java.nio.file.WatchEvent; +import java.nio.file.WatchKey; +import java.nio.file.WatchService; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.tizen.emulator.manager.resources.FilePathResources; + +abstract class LockFileMonitor extends RunningMonitor { + private final WatchService watcher; + + protected final List lockedFiles = new ArrayList(); + + private final Map keys; + protected final Path lockfilePath; + + + LockFileMonitor() throws IOException { + watcher = FileSystems.getDefault().newWatchService(); + keys = new HashMap(); + // XXX: We concern only image files / lockfiles under Tizen sdk data VMS path + lockfilePath = Paths.get(FilePathResources.getTizenVmsPath()); + + assert !(Files.notExists(lockfilePath)); + + new MonitoringThread(new FileMonitorThread(), "LockFileMonitor").start(); + } + + abstract protected boolean isMonitoringFile(Path path); + abstract protected void handleExistFile(Path path); + + protected void registerDirectory(Path path) throws IOException { + assert Files.isDirectory(path); + + WatchKey key = path.register(watcher, StandardWatchEventKinds.ENTRY_CREATE, + StandardWatchEventKinds.ENTRY_DELETE); + keys.put(key, path); + } + + private void traverseSubdirectory(final Path start) throws IOException { + assert Files.isDirectory(start); + + // register sub-directories + Files.walkFileTree(start, Collections. emptySet(), 2, + new SimpleFileVisitor() { + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) + throws IOException + { + registerDirectory(dir); + + // we should watch already have been launched VMs + DirectoryStream stream = Files.newDirectoryStream(dir); + for (Path path : stream) { + if (Files.isRegularFile(path) && isMonitoringFile(path)) { + handleExistFile(path); + } + } + + return FileVisitResult.CONTINUE; + } + }); + } + + private void registerWatchRoot() throws InterruptedException, IOException { + boolean isRootRegistered = false; + WatchKey key = null; + + while(!isRootRegistered) { + try { + key = lockfilePath.register(watcher, StandardWatchEventKinds.ENTRY_CREATE, + StandardWatchEventKinds.ENTRY_DELETE); + } catch(NoSuchFileException e) { + // failsafe, can not enter here. + Thread.sleep(1000); + continue; + } catch(IOException e) { + // FIXME + e.printStackTrace(); + } + isRootRegistered = true; + keys.put(key, lockfilePath); + } + + traverseSubdirectory(lockfilePath); + } + + abstract protected void entryCreated(Path path) throws IOException; + abstract protected void entryDeleted(Path path) throws IOException; + + private final class FileMonitorThread implements Runnable { + @Override + public void run() { + WatchKey key = null; + + try { + registerWatchRoot(); + + while(true) { + key = watcher.take(); + + Path dir = keys.get(key); + if (dir == null) { + continue; + } + + for (WatchEvent event : key.pollEvents()) { + Path path = dir.resolve((Path)event.context()); + + if (event.kind() == StandardWatchEventKinds.ENTRY_CREATE) { + entryCreated(path); + } + + if (event.kind() == StandardWatchEventKinds.ENTRY_DELETE) { + entryDeleted(path); + } + } + + if(!key.reset()) { + keys.remove(key); + } + } + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + } +} \ No newline at end of file diff --git a/src/org/tizen/emulator/manager/vms/monitor/MonitoringThread.java b/src/org/tizen/emulator/manager/vms/monitor/MonitoringThread.java new file mode 100644 index 0000000..5c1922c --- /dev/null +++ b/src/org/tizen/emulator/manager/vms/monitor/MonitoringThread.java @@ -0,0 +1,83 @@ +/* + * Emulator Manager + * + * Copyright (C) 2011 - 2016 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * JiHye Kim + * Minkee Lee + * + * This program 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. + * + * This program 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +package org.tizen.emulator.manager.vms.monitor; + +import org.tizen.emulator.manager.logging.EMLogger; + +final class MonitoringThread extends Thread { + private final int timeoutSec; + + public MonitoringThread(Runnable runnable, String name, int timeoutSec) { + super(runnable); + // Monitoring thread should be exit immediately when emulator-manager is terminated + this.setDaemon(true); + + this.timeoutSec = timeoutSec; + } + + public MonitoringThread(Runnable runnable, String name) { + this(runnable, name, 0); + } + + @Override + public void start() { + // Start timer for interrupting launching monitor + if (timeoutSec > 0) { + new TimerThread(this, timeoutSec).start(); + } + + super.start(); + } +} + +final class TimerThread extends Thread { + private Thread thread; + private int sec; + + TimerThread(Thread thread, int sec) { + this.thread = thread; + this.sec = sec; + + this.setDaemon(true); + } + + @Override + public void run() { + synchronized (this) { + try { + this.wait(sec * 1000); + } catch (InterruptedException e) { + EMLogger.getLogger().warning(e.getMessage()); + } + } + + thread.interrupt(); + } +} \ No newline at end of file diff --git a/src/org/tizen/emulator/manager/vms/monitor/PosixLockFileMonitor.java b/src/org/tizen/emulator/manager/vms/monitor/PosixLockFileMonitor.java new file mode 100644 index 0000000..28d44d5 --- /dev/null +++ b/src/org/tizen/emulator/manager/vms/monitor/PosixLockFileMonitor.java @@ -0,0 +1,150 @@ +/* + * Emulator Manager + * + * Copyright (C) 2011 - 2016 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * JiHye Kim + * Minkee Lee + * + * This program 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. + * + * This program 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +package org.tizen.emulator.manager.vms.monitor; + +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.tizen.emulator.manager.vms.VMProperty; + +final class PosixLockFileMonitor extends LockFileMonitor { + protected final List monitoredFiles = + Collections.synchronizedList(new ArrayList()); + + PosixLockFileMonitor() throws IOException { + super(); + + new MonitoringThread(new LockMonitorThread(), "PosixLockMonitor").start(); + } + + @Override + protected boolean isMonitoringFile(Path path) { + for (VMProperty.Architecture arch : VMProperty.Architecture.values()) { + if (path.toString().endsWith("." + arch.toString())) { + return true; + } + } + + return false; + } + + @Override + protected void handleExistFile(Path path) { + monitoredFiles.add(path); + } + + @Override + protected void entryCreated(Path path) throws IOException { + if (Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS)) { + if (path.getParent().equals(lockfilePath)) { + registerDirectory(path); + } + + return; + } + + if (!Files.isRegularFile(path)) { + return; + } + + assert !monitoredFiles.contains(path); + + monitoredFiles.add(path); + } + + @Override + protected void entryDeleted(Path path) throws IOException { + if (!Files.isRegularFile(path)) { + return; + } + + boolean result = monitoredFiles.remove(path); + + assert result; + } + + private synchronized boolean examineLock(Path path) throws IOException { + FileChannel fc = FileChannel.open(path, StandardOpenOption.WRITE); + FileLock lock = fc.tryLock(); + + if (lock != null && lock.isValid()) { + lock.release(); + fc.close(); + + if (lockedFiles.remove(path)) { + updateState(path, false); + } + + return false; + } + + if (!lockedFiles.contains(path)) { + lockedFiles.add(path); + updateState(path, true); + } + + fc.close(); + + return true; + } + + private final class LockMonitorThread implements Runnable { + @Override + public void run() { + while (true) { + try { + synchronized (monitoredFiles) { + for (Path path : monitoredFiles) { + try { + examineLock(path); + } catch (NoSuchFileException e) { + // Ignore it + } + } + } + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } +} \ No newline at end of file diff --git a/src/org/tizen/emulator/manager/vms/monitor/RunningMonitor.java b/src/org/tizen/emulator/manager/vms/monitor/RunningMonitor.java new file mode 100644 index 0000000..1753395 --- /dev/null +++ b/src/org/tizen/emulator/manager/vms/monitor/RunningMonitor.java @@ -0,0 +1,178 @@ +/* + * Emulator Manager + * + * Copyright (C) 2011 - 2016 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * JiHye Kim + * Minkee Lee + * + * This program 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. + * + * This program 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +package org.tizen.emulator.manager.vms.monitor; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.tizen.emulator.manager.EmulatorManager; +import org.tizen.emulator.manager.vms.EmulatorVMList; +import org.tizen.emulator.manager.vms.VMProperty; +import org.tizen.emulator.manager.vms.VMProperty.State; + +public class RunningMonitor { + private static Thread updater; + + private static Map> monitoredVMs = new HashMap>(); + private static List> pendingJobs = + Collections.synchronizedList(new ArrayList>()); + + private List ignoredVMs = new ArrayList(); + + + protected RunningMonitor() { + synchronized (RunningMonitor.class) { + if (updater == null) { + updater = new Thread(new Updater()); + updater.setDaemon(true); + updater.start(); + } + } + } + + protected void updateState(Path imagePath, boolean isRunningDetected) { + MonitoringState mstate = new MonitoringState(imagePath, isRunningDetected); + + synchronized (monitoredVMs) { + if (isRunningDetected) { + if (monitoredVMs.containsKey(imagePath)) { + // XXX: prevent double check by multiple monitor + // monitors must not call it again with same state + ignoredVMs.add(imagePath); + + return; + } + + monitoredVMs.put(imagePath, mstate); + } else { + if (ignoredVMs.remove(imagePath)) { + return; + } + + MonitoringState result = monitoredVMs.remove(imagePath); + + assert result != null; + } + } + + pendingJobs.add(mstate); + // update state immediately + updatePended(); + } + + private void updatePended() { + synchronized (pendingJobs) { + Iterator> iter = pendingJobs.iterator(); + while (iter.hasNext()) { + MonitoringState mstate = iter.next(); + VMProperty property = EmulatorVMList.getInstance().getProperty(mstate.object); + State updateState = mstate.isRunningDetected ? State.RUNNING : State.READY; + + if (property != null && property.setState(updateState)) { + iter.remove(); + } + } + } + } + + public static void refreshAll() { + synchronized (monitoredVMs) { + synchronized (pendingJobs) { + // just add all monitoring states into a pending job list + // it will be set again by Updater thread soon + for (MonitoringState mstate : monitoredVMs.values()) { + pendingJobs.add(mstate); + } + } + } + } + + public static synchronized void initialize() throws IOException { + // do not initialize again + assert updater == null; + + // for recent emulator + if (EmulatorManager.isWin()) { + // TODO: not tested yet + // new WindowsLockFileMonitor(); + } else { + new PosixLockFileMonitor(); + } + + // for legacy emulator + new ECSMonitor(); + } + + private final class Updater implements Runnable { + @Override + public void run() { + while (true) { + updatePended(); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } +} + +final class MonitoringState { + final T object; + boolean isRunningDetected; + + public MonitoringState(T object, boolean isRunningDetected) { + this.object = object; + this.isRunningDetected = isRunningDetected; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof MonitoringState)) { + return false; + } + + @SuppressWarnings("unchecked") + T obj2 = ((MonitoringState)obj).object; + if (obj2.equals(object)) { + return true; + } + + return false; + } +} diff --git a/src/org/tizen/emulator/manager/vms/monitor/WindowsLockFileMonitor.java b/src/org/tizen/emulator/manager/vms/monitor/WindowsLockFileMonitor.java new file mode 100644 index 0000000..056bf6b --- /dev/null +++ b/src/org/tizen/emulator/manager/vms/monitor/WindowsLockFileMonitor.java @@ -0,0 +1,101 @@ +/* + * Emulator Manager + * + * Copyright (C) 2011 - 2016 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * JiHye Kim + * Minkee Lee + * + * This program 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. + * + * This program 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +package org.tizen.emulator.manager.vms.monitor; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.Path; + +final class WindowsLockFileMonitor extends LockFileMonitor { + WindowsLockFileMonitor() throws IOException { + super(); + } + + @Override + protected boolean isMonitoringFile(Path path) { + if (path.toString().endsWith(".lock")) { + return true; + } + + return false; + } + + @Override + protected void handleExistFile(Path path) { + // all .lock files are locked + lockedFiles.add(path); + updateState(path, true); + } + + @Override + protected void entryCreated(Path path) throws IOException { + if (Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS)) { + if (path.getParent().equals(lockfilePath)) { + registerDirectory(path); + } + + return; + } + + if (!isMonitoringFile(path) || !Files.isRegularFile(path)) { + return; + } + + assert !lockedFiles.contains(path); + + lockedFiles.add(path); + updateState(path, true); + } + + @Override + protected void entryDeleted(Path path) throws IOException { + if (!isMonitoringFile(path)) { + return; + } + + assert lockedFiles.contains(path); + + lockedFiles.remove(path); + updateState(path, false); + } + + @Override + protected void updateState(Path path, boolean isRunningDetected) { + // path is lock file path + // lock file -> image file + .lock + // updateState need image file path + File tempFile = path.toFile(); + File imageFile = new File(tempFile.getAbsolutePath().substring(0, + tempFile.getAbsolutePath().lastIndexOf('.'))); + super.updateState(imageFile.toPath(), isRunningDetected); + } +} \ No newline at end of file -- 2.7.4