From: SeokYeon Hwang Date: Sat, 16 Jan 2016 04:52:03 +0000 (+0900) Subject: monitoring: fix bugs and do addidional refatoring X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8df967487d2b3f6285d6c9d52b9314a88550913c;p=sdk%2Femulator%2Femulator-manager.git monitoring: fix bugs and do addidional refatoring WatchService inside LockFileMonitor is FileWatcher now. It will be used by other file-based monitoring. Fixed a bug on LaunchingMonitor when run as CLI. And some codes are refined. Change-Id: Ia7d822ededfac958863f52ca5855560335e2836d Signed-off-by: SeokYeon Hwang --- diff --git a/src/org/tizen/emulator/manager/EmulatorManager.java b/src/org/tizen/emulator/manager/EmulatorManager.java index 3640994..480e2c9 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.FileWatcher; import org.tizen.emulator.manager.vms.monitor.RunningMonitor; import com.sun.jna.Native; @@ -354,6 +355,8 @@ public class EmulatorManager { CheckVT.class, CheckGPU.class, CheckSDCard.class, CheckWebcam.class); checkers.startWork(); + // initializing monitors + FileWatcher.initialize(); RunningMonitor.initialize(); } diff --git a/src/org/tizen/emulator/manager/ui/dialog/CloneDialog.java b/src/org/tizen/emulator/manager/ui/dialog/CloneDialog.java index 8687698..08440da 100644 --- a/src/org/tizen/emulator/manager/ui/dialog/CloneDialog.java +++ b/src/org/tizen/emulator/manager/ui/dialog/CloneDialog.java @@ -46,8 +46,8 @@ import org.tizen.emulator.manager.resources.ImageResources; import org.tizen.emulator.manager.resources.StringResources; import org.tizen.emulator.manager.ui.MainDialog; import org.tizen.emulator.manager.vms.VMProperty; -import org.tizen.emulator.manager.vms.helper.VMWorkerException; import org.tizen.emulator.manager.vms.helper.HelperClass; +import org.tizen.emulator.manager.vms.helper.VMWorkerException; public class CloneDialog { private VMProperty property = null; @@ -58,7 +58,7 @@ public class CloneDialog { private Button cancelButton = null; private String vmName = null; - + public CloneDialog(VMProperty prop) { property = prop; } @@ -98,10 +98,10 @@ public class CloneDialog { cancelButton.setImage(ImageResources.CANCEL.getImage()); addListener(); - + dialog.open(); } - + private void addListener() { name.addModifyListener(new ModifyListener() { @Override @@ -110,7 +110,7 @@ public class CloneDialog { checkImageName(); } }); - + confirmButton.addSelectionListener(new SelectionListener() { @Override public void widgetDefaultSelected(SelectionEvent event) { @@ -121,7 +121,7 @@ public class CloneDialog { String message = ""; //$NON-NLS-1$ try { property.getWorker().cloneVM(vmName); - //message = "Emulator cloning completed!"; + //message = "Emulator cloning completed!"; } catch (VMWorkerException e) { message = e.getMessage(); msg.openInfoDialog(message); @@ -132,9 +132,9 @@ public class CloneDialog { MainDialog.refreshVMPropertyList(true); //mainDialog.vmsTree.setSelectProperty(property); } - + }); - + cancelButton.addSelectionListener(new SelectionListener() { @Override public void widgetDefaultSelected(SelectionEvent arg) { @@ -146,10 +146,10 @@ public class CloneDialog { MainDialog.refreshVMPropertyList(true); //mainDialog.vmsTree.setSelectProperty(property); } - + }); } - + private void checkImageName() { /* if (vmName.length() > VMPropertyView.MAX_NAME_LEN) { diff --git a/src/org/tizen/emulator/manager/ui/renewal/widgets/CreateVMCombo.java b/src/org/tizen/emulator/manager/ui/renewal/widgets/CreateVMCombo.java index 5bc541e..290193e 100644 --- a/src/org/tizen/emulator/manager/ui/renewal/widgets/CreateVMCombo.java +++ b/src/org/tizen/emulator/manager/ui/renewal/widgets/CreateVMCombo.java @@ -140,7 +140,8 @@ public class CreateVMCombo extends Canvas { } public void add(ProfileButton item, int index) { - assert item == null; + assert item != null; + if (index < 0 || index > items.size()) { // TODO return; diff --git a/src/org/tizen/emulator/manager/vms/VMLauncher.java b/src/org/tizen/emulator/manager/vms/VMLauncher.java index f80a133..4742228 100644 --- a/src/org/tizen/emulator/manager/vms/VMLauncher.java +++ b/src/org/tizen/emulator/manager/vms/VMLauncher.java @@ -53,7 +53,6 @@ import org.tizen.emulator.manager.vms.option.NetProxyOption; import org.tizen.emulator.manager.vms.option.OPTION_KEY; public class VMLauncher { - public static boolean Launch(VMProperty property, boolean wait, String path) throws VMLauncherException { @@ -65,17 +64,16 @@ public class VMLauncher { String emulatorPath = property.getPropertyValue().baseImage.getPlatform().getEmulatorPath(); - Process process = launch(property.getName(), emulatorPath, cmd, path); + Process process = launchInternal(property.getName(), emulatorPath, cmd, path); if (process == null) { return false; } LaunchingMonitor monitor = new LaunchingMonitor(property, process); - if (!wait) { - monitor.asyncExecute(8); // timeout : 8 seconds + monitor.asyncExecute(); - return true; + return true; // we can not determine whether VM is launched successfully or not } return monitor.execute(); @@ -159,7 +157,7 @@ public class VMLauncher { } } - public static Process launch(String vmName, String emulatorPath, + private static Process launchInternal(String vmName, String emulatorPath, List cmd, String binPath) { ProcessBuilder pb = new ProcessBuilder(cmd); EMLogger.getLogger().log(Level.INFO, "Command list for ProcessBuilder"); diff --git a/src/org/tizen/emulator/manager/vms/VMPropertyValue.java b/src/org/tizen/emulator/manager/vms/VMPropertyValue.java index 29d083b..e5f8463 100644 --- a/src/org/tizen/emulator/manager/vms/VMPropertyValue.java +++ b/src/org/tizen/emulator/manager/vms/VMPropertyValue.java @@ -134,7 +134,7 @@ public class VMPropertyValue implements Cloneable { * @param property property of emulator */ public VMPropertyValue(VMProperty property) { - assert property == null; + assert property != null; if (property != null) { this.template = property; diff --git a/src/org/tizen/emulator/manager/vms/monitor/FileWatchEventListener.java b/src/org/tizen/emulator/manager/vms/monitor/FileWatchEventListener.java new file mode 100644 index 0000000..0a4a743 --- /dev/null +++ b/src/org/tizen/emulator/manager/vms/monitor/FileWatchEventListener.java @@ -0,0 +1,10 @@ +package org.tizen.emulator.manager.vms.monitor; + +import java.nio.file.Path; + +interface FileWatchEventListener { + void preexistingDirectoryFound(Path dir); + void entryCreated(Path path); + void entryModified(Path path); + void entryDeleted(Path path); +} diff --git a/src/org/tizen/emulator/manager/vms/monitor/FileWatcher.java b/src/org/tizen/emulator/manager/vms/monitor/FileWatcher.java new file mode 100644 index 0000000..e6ece6c --- /dev/null +++ b/src/org/tizen/emulator/manager/vms/monitor/FileWatcher.java @@ -0,0 +1,168 @@ +package org.tizen.emulator.manager.vms.monitor; + +import java.io.IOException; +import java.nio.file.FileSystems; +import java.nio.file.FileVisitOption; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.LinkOption; +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; + +public final class FileWatcher implements Runnable, FileWatchEventListener { + static FileWatcher instance; + + private final WatchService watcher; + private final Map keys; + private final Path watchPath; + private final List eventListener; + + + public static synchronized void initialize() throws IOException { + // We do not use static block since we want initialize FileWatcher explicitly. + + // do not initialize again + assert instance == null; + + instance = new FileWatcher(); + instance.registerDefaultPath(); + + new MonitoringThread(instance, "FileWatcher").start(); + } + + private FileWatcher() throws IOException { + watcher = FileSystems.getDefault().newWatchService(); + keys = new HashMap(); + // XXX: We concern only image files / lockfiles under Tizen sdk data VMS path + watchPath = Paths.get(FilePathResources.getTizenVmsPath()); + eventListener = new ArrayList(); + + assert Files.exists(watchPath); + } + + static final void addListener(FileWatchEventListener listener) throws IOException { + instance.eventListener.add(listener); + instance.traverseWatchedDirectories(listener); + } + + private void registerDirectory(Path path) { + assert Files.isDirectory(path); + + WatchKey key = null; + try { + key = path.register(watcher, StandardWatchEventKinds.ENTRY_CREATE, + StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY); + keys.put(key, path); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void traverseWatchedDirectories(final FileWatchEventListener listener) throws IOException { + // we concern *one* depth sub-directories only + Files.walkFileTree(watchPath, Collections. emptySet(), 2, + new SimpleFileVisitor() { + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) + throws IOException + { + listener.preexistingDirectoryFound(dir); + + return FileVisitResult.CONTINUE; + } + }); + } + + private void registerDefaultPath() throws IOException { + WatchKey key = null; + + try { + key = watchPath.register(watcher, StandardWatchEventKinds.ENTRY_CREATE, + StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY); + } catch(IOException e) { + // FIXME + e.printStackTrace(); + } + keys.put(key, watchPath); + + addListener(this); + } + + @Override + public void run() { + WatchKey key = null; + + try { + 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()); + + for (FileWatchEventListener listener : eventListener) { + if (event.kind() == StandardWatchEventKinds.ENTRY_CREATE) { + listener.entryCreated(path); + } + + if (event.kind() == StandardWatchEventKinds.ENTRY_MODIFY) { + listener.entryModified(path); + } + + if (event.kind() == StandardWatchEventKinds.ENTRY_DELETE) { + listener.entryDeleted(path); + } + } + } + + if(!key.reset()) { + keys.remove(key); + } + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + @Override + public void preexistingDirectoryFound(Path dir) { + registerDirectory(dir); + } + + @Override + public void entryCreated(Path path) { + if (Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS)) { + if (path.getParent().equals(watchPath)) { + registerDirectory(path); + } + return; + } + } + + @Override + public void entryModified(Path path) { + // do nothing + } + + @Override + public void entryDeleted(Path path) { + // do nothing + } +} diff --git a/src/org/tizen/emulator/manager/vms/monitor/LaunchingMonitor.java b/src/org/tizen/emulator/manager/vms/monitor/LaunchingMonitor.java index cbfdb8a..cb01e3a 100644 --- a/src/org/tizen/emulator/manager/vms/monitor/LaunchingMonitor.java +++ b/src/org/tizen/emulator/manager/vms/monitor/LaunchingMonitor.java @@ -5,7 +5,6 @@ * * Contact: * JiHye Kim - * YeongKyoon Lee * SeokYeon Hwang * * This program is free software; you can redistribute it and/or @@ -29,10 +28,6 @@ package org.tizen.emulator.manager.vms.monitor; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.ArrayList; import java.util.logging.Level; import org.eclipse.swt.widgets.Display; @@ -46,192 +41,98 @@ import org.tizen.emulator.manager.vms.VMProperty; public final class LaunchingMonitor implements Runnable { private final VMProperty property; private final Process process; - private Output stdOut = null; - private Output stdErr = null; + + private int timeoutSec; + private int exitValue = -1; public LaunchingMonitor(VMProperty property, Process process) { + assert property != null; + assert process != null; + this.property = property; this.process = process; } - public boolean execute() { - if (process == null || property == null) { - return false; - } - - boolean success = true; - - BufferedReader readerOut = new BufferedReader(new InputStreamReader(process.getInputStream())); - BufferedReader readerError = new BufferedReader(new InputStreamReader(process.getErrorStream())); - - 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$ - - t1.start(); - t2.start(); - - try { - int exitValue = process.waitFor(); - - EMLogger.getLogger().warning( - String.format( - "Emulator has been terminated. Exit value: %X(%d)", //$NON-NLS-1$ - exitValue, exitValue)); - stdOut.printMessageList(); - stdErr.printMessageList(); - - if (exitValue != 0) { - 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$ - if (!EmulatorManager.isConsoleMode()) { - Display.getDefault().asyncExec(new Runnable() { - - @Override - public void run() { - // TODO - new MessageDialog() - .openWarningDialog(Messages.getString("MonitoringEmulator.RunningError.0") //$NON-NLS-1$ - + StringResources.NEW_LINE - + Messages.getString("MonitoringEmulator.RunningError.1") //$NON-NLS-1$ - + StringResources.NEW_LINE - + Messages.getString("MonitoringEmulator.RunningError.2") //$NON-NLS-1$ - + property.getName() - + Messages.getString("MonitoringEmulator.RunningError.3")); //$NON-NLS-1$ - } - - }); + private boolean executeInternal() { + Thread waitingThread = new MonitoringThread(new Runnable() { + @Override + public void run() { + try { + exitValue = process.waitFor(); + } catch (InterruptedException e) { + // launched successfully + EMLogger.getLogger().log(Level.FINE, e.getMessage()); } } - } catch (InterruptedException e) { - // launched successfully - EMLogger.getLogger().log(Level.FINE, e.getMessage()); - } + }, "Waiting VM process " + property.getName()); - stdOut.setDone(); - stdErr.setDone(); + waitingThread.start(); try { - t1.join(); - t2.join(); + waitingThread.join(1000 * timeoutSec); } catch (InterruptedException e) { - EMLogger.getLogger().warning(e.getMessage()); - } - - // close - try { - if (readerOut != null) { - readerOut.close(); - } - if (readerError != null) { - readerError.close(); - } - } catch (IOException e) { - EMLogger.getLogger().warning(e.getMessage()); + e.printStackTrace(); } - return success; - } + if (exitValue == -1) { + // VM process may be running well. Stop monitoring VM process. + waitingThread.interrupt(); - public void asyncExecute(int timeoutSec) { - new MonitoringThread(this, "LunchingMonitor", timeoutSec).start(); - } + return true; + } - @Override - public void run() { - property.setState(VMProperty.State.LAUNCHING); + if (exitValue == 0) { + // VM process exit in timeout. + EMLogger.getLogger().warning( + String.format( + "Emulator has been terminated in " + timeoutSec + "seconds.")); //$NON-NLS-1$ - if (!execute()) { - property.setState(VMProperty.State.READY); + // TODO: check about it. + return true; } - } -} -final class Output implements Runnable { - private BufferedReader reader; - private String vmName; - private final ArrayList list = new ArrayList(); + // VM process may be terminated with error. + 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$ + if (!EmulatorManager.isConsoleMode()) { + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + // TODO + new MessageDialog() + .openWarningDialog(Messages.getString("MonitoringEmulator.RunningError.0") //$NON-NLS-1$ + + StringResources.NEW_LINE + + Messages.getString("MonitoringEmulator.RunningError.1") //$NON-NLS-1$ + + StringResources.NEW_LINE + + Messages.getString("MonitoringEmulator.RunningError.2") //$NON-NLS-1$ + + property.getName() + + Messages.getString("MonitoringEmulator.RunningError.3")); //$NON-NLS-1$ + } + }); + } - private boolean isDone = false; - private boolean error = false; + return false; + } + public boolean execute() { + timeoutSec = 8; // timeout : 8 seconds - Output(BufferedReader reader, String name) { - this.reader = reader; - this.vmName = name; + return executeInternal(); } - Output(InputStreamReader in, String name) { - this.reader = new BufferedReader(in); - this.vmName = name; - } + public void asyncExecute() { + timeoutSec = 8; // timeout : 8 seconds - void setDone() { - this.isDone = true; + new MonitoringThread(this, "LaunchingMonitor").start(); } @Override public void run() { - String msg = ""; //$NON-NLS-1$ - - if (reader != null) { - char c; - int i; - try { - do { - if (reader.ready()) { // To avoid blocking in following read() - i = (reader.read()); - if (i == -1) { // EOF - break; - } - if (Thread.currentThread().getName() - .equals(vmName + "STDERR")) { //$NON-NLS-1$ - c = (char) i; - msg += c; - if (msg.contains(StringResources.NEW_LINE)) { - // Remove NEW_LINE - msg = msg.substring(0, msg.length() - - StringResources.NEW_LINE.length()); - list.add(msg); // Add msg from STDERR. - msg = ""; //$NON-NLS-1$ - } - } - - } else { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - } while (!isDone); - } catch (IOException e) { - EMLogger.getLogger().info(e.getMessage()); - } finally { - try { - reader.close(); - } catch (IOException e) { - EMLogger.getLogger().warning(e.getMessage()); - } - } - } + property.setState(VMProperty.State.LAUNCHING); - if (error) { - for (String s : list) { - if (s != null && !s.isEmpty()) { - EMLogger.getLogger().warning( - "Print Log From Emulator: " + s); //$NON-NLS-1$ - } - } + if (!executeInternal()) { + property.setState(VMProperty.State.READY); } } - - 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 index 1290ab9..007ae0a 100644 --- a/src/org/tizen/emulator/manager/vms/monitor/LockFileMonitor.java +++ b/src/org/tizen/emulator/manager/vms/monitor/LockFileMonitor.java @@ -30,148 +30,14 @@ 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; +abstract class LockFileMonitor extends RunningMonitor implements FileWatchEventListener { + protected final List lockedFiles; 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(); - } - } - + lockedFiles = new ArrayList(); } } \ 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 index 5c1922c..40c409b 100644 --- a/src/org/tizen/emulator/manager/vms/monitor/MonitoringThread.java +++ b/src/org/tizen/emulator/manager/vms/monitor/MonitoringThread.java @@ -29,55 +29,10 @@ 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) { + public MonitoringThread(Runnable runnable, String name) { 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 index 28d44d5..e46d607 100644 --- a/src/org/tizen/emulator/manager/vms/monitor/PosixLockFileMonitor.java +++ b/src/org/tizen/emulator/manager/vms/monitor/PosixLockFileMonitor.java @@ -32,10 +32,12 @@ 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.DirectoryStream; +import java.nio.file.FileSystems; import java.nio.file.Files; -import java.nio.file.LinkOption; import java.nio.file.NoSuchFileException; import java.nio.file.Path; +import java.nio.file.PathMatcher; import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.Collections; @@ -44,59 +46,30 @@ import java.util.List; import org.tizen.emulator.manager.vms.VMProperty; final class PosixLockFileMonitor extends LockFileMonitor { - protected final List monitoredFiles = - Collections.synchronizedList(new ArrayList()); + private final PathMatcher matcher; + protected final List monitoredFiles; - PosixLockFileMonitor() throws IOException { - super(); - - new MonitoringThread(new LockMonitorThread(), "PosixLockMonitor").start(); - } - @Override - protected boolean isMonitoringFile(Path path) { + PosixLockFileMonitor() throws IOException { + StringBuffer matchExtension = new StringBuffer(); 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; + matchExtension.append(arch.toString()).append(","); } - if (!Files.isRegularFile(path)) { - return; - } - - assert !monitoredFiles.contains(path); + matcher = FileSystems.getDefault().getPathMatcher("glob:*.{" + matchExtension.toString() + "}"); + monitoredFiles = + Collections.synchronizedList(new ArrayList()); + FileWatcher.addListener(this); - monitoredFiles.add(path); + new MonitoringThread(new LockMonitorThread(), "PosixLockMonitor").start(); } - @Override - protected void entryDeleted(Path path) throws IOException { - if (!Files.isRegularFile(path)) { - return; + private boolean isMonitoringFile(Path path) { + if (matcher.matches(path) && Files.isRegularFile(path)) { + return true; } - boolean result = monitoredFiles.remove(path); - - assert result; + return false; } private synchronized boolean examineLock(Path path) throws IOException { @@ -124,6 +97,42 @@ final class PosixLockFileMonitor extends LockFileMonitor { return true; } + @Override + public void preexistingDirectoryFound(Path dir) { +; try { + DirectoryStream stream = Files.newDirectoryStream(dir); + + for (Path path : stream) { + if (Files.isRegularFile(path) && isMonitoringFile(path)) { + monitoredFiles.add(path); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void entryCreated(Path path) { + if (!isMonitoringFile(path)) { + return; + } + + assert !monitoredFiles.contains(path); + + monitoredFiles.add(path); + } + + @Override + public void entryModified(Path path) { + // do nothing + } + + @Override + public void entryDeleted(Path path) { + monitoredFiles.remove(path); + } + private final class LockMonitorThread implements Runnable { @Override public void run() { diff --git a/src/org/tizen/emulator/manager/vms/monitor/RunningMonitor.java b/src/org/tizen/emulator/manager/vms/monitor/RunningMonitor.java index 1753395..40fee9d 100644 --- a/src/org/tizen/emulator/manager/vms/monitor/RunningMonitor.java +++ b/src/org/tizen/emulator/manager/vms/monitor/RunningMonitor.java @@ -43,7 +43,7 @@ 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 { +public abstract class RunningMonitor { private static Thread updater; private static Map> monitoredVMs = new HashMap>(); @@ -121,6 +121,8 @@ public class RunningMonitor { } public static synchronized void initialize() throws IOException { + // FileWatcher had been initialized. + assert FileWatcher.instance != null; // do not initialize again assert updater == null; diff --git a/src/org/tizen/emulator/manager/vms/monitor/WindowsLockFileMonitor.java b/src/org/tizen/emulator/manager/vms/monitor/WindowsLockFileMonitor.java index 056bf6b..3e1d386 100644 --- a/src/org/tizen/emulator/manager/vms/monitor/WindowsLockFileMonitor.java +++ b/src/org/tizen/emulator/manager/vms/monitor/WindowsLockFileMonitor.java @@ -29,20 +29,24 @@ package org.tizen.emulator.manager.vms.monitor; -import java.io.File; import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.FileSystems; import java.nio.file.Files; -import java.nio.file.LinkOption; import java.nio.file.Path; +import java.nio.file.PathMatcher; +import java.nio.file.Paths; final class WindowsLockFileMonitor extends LockFileMonitor { + private final PathMatcher matcher; + + WindowsLockFileMonitor() throws IOException { - super(); + matcher = FileSystems.getDefault().getPathMatcher("glob:*.java"); } - @Override - protected boolean isMonitoringFile(Path path) { - if (path.toString().endsWith(".lock")) { + private boolean isMonitoringFile(Path path) { + if (matcher.matches(path) && Files.isRegularFile(path)) { return true; } @@ -50,23 +54,25 @@ final class WindowsLockFileMonitor extends LockFileMonitor { } @Override - protected void handleExistFile(Path path) { - // all .lock files are locked - lockedFiles.add(path); - updateState(path, true); - } + public void preexistingDirectoryFound(Path dir) { + try { + DirectoryStream stream = Files.newDirectoryStream(dir); - @Override - protected void entryCreated(Path path) throws IOException { - if (Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS)) { - if (path.getParent().equals(lockfilePath)) { - registerDirectory(path); + for (Path path : stream) { + if (isMonitoringFile(path)) { + // all .lock files are locked + lockedFiles.add(path); + updateState(path, true); + } } - - return; + } catch (IOException e) { + e.printStackTrace(); } + } - if (!isMonitoringFile(path) || !Files.isRegularFile(path)) { + @Override + public void entryCreated(Path path) { + if (!isMonitoringFile(path)) { return; } @@ -77,7 +83,12 @@ final class WindowsLockFileMonitor extends LockFileMonitor { } @Override - protected void entryDeleted(Path path) throws IOException { + public void entryModified(Path path) { + // do nothing + } + + @Override + public void entryDeleted(Path path) { if (!isMonitoringFile(path)) { return; } @@ -93,9 +104,8 @@ final class WindowsLockFileMonitor extends LockFileMonitor { // 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); + Path imagePath = Paths.get(path.toString().substring(0, + path.toString().lastIndexOf('.'))); + super.updateState(imagePath, isRunningDetected); } } \ No newline at end of file