You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by ke...@apache.org on 2011/04/08 18:56:59 UTC
svn commit: r1090351 - in /geronimo/server/trunk/plugins/hotdeploy:
geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/
hot-deployer/src/main/plan/
Author: kevan
Date: Fri Apr 8 16:56:59 2011
New Revision: 1090351
URL: http://svn.apache.org/viewvc?rev=1090351&view=rev
Log:
GERONIMO-5891 persist the DirectoryMonitor state to disk. Used to read initial state on server start. So, hot-deploy changes made while server was stopped can be processed
Modified:
geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java
geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java
geronimo/server/trunk/plugins/hotdeploy/hot-deployer/src/main/plan/plan.xml
Modified: geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java?rev=1090351&r1=1090350&r2=1090351&view=diff
==============================================================================
--- geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java (original)
+++ geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java Fri Apr 8 16:56:59 2011
@@ -65,6 +65,7 @@ public class DirectoryHotDeployer implem
"is 'deploy/' and your file is 'webapp.war' then you could unpack it into a directory 'deploy/webapp.war/'";
private DirectoryMonitor monitor;
private String path;
+ private String monitorFileName;
private ServerInfo serverInfo;
private ConfigurationManager configManager;
private int pollIntervalMillis;
@@ -76,8 +77,10 @@ public class DirectoryHotDeployer implem
private transient TargetModuleID[] startupModules = null;
private transient boolean serverRunning = false;
- public DirectoryHotDeployer(String path, int pollIntervalMillis, ServerInfo serverInfo, ConfigurationManager configManager, Kernel kernel) {
+ public DirectoryHotDeployer(String path, String monitorFileName, int pollIntervalMillis,
+ ServerInfo serverInfo, ConfigurationManager configManager, Kernel kernel) {
this.path = path;
+ this.monitorFileName = monitorFileName;
this.serverInfo = serverInfo;
this.pollIntervalMillis = pollIntervalMillis;
this.kernel = kernel;
@@ -147,6 +150,7 @@ public class DirectoryHotDeployer implem
if (factory == null) {
factory = new DeploymentFactoryWithKernel(kernel);
}
+
File dir = serverInfo.resolveServer(path);
if (!dir.exists()) {
if (!dir.mkdirs()) {
@@ -155,6 +159,17 @@ public class DirectoryHotDeployer implem
} else if (!dir.canRead() || !dir.isDirectory()) {
throw new IllegalStateException("Hot deploy directory " + dir.getAbsolutePath() + " is not a readable directory!");
}
+
+ File monitorFile = null;
+ if (monitorFileName != null && !monitorFileName.isEmpty()) {
+ monitorFile = serverInfo.resolveServer(dir + File.separator + monitorFileName);
+ if (!monitorFile.createNewFile()) {
+ if (!monitorFile.canWrite()) {
+ throw new IllegalStateException("Hot deploy persist state file " + monitorFile.getAbsolutePath() + " could not be created or is not writable");
+ }
+ }
+ }
+
DeploymentManager mgr = null;
try {
mgr = getDeploymentManager();
@@ -162,7 +177,7 @@ public class DirectoryHotDeployer implem
startupModules = mgr.getAvailableModules(null, targets);
mgr.release();
mgr = null;
- monitor = new DirectoryMonitor(dir, this, pollIntervalMillis);
+ monitor = new DirectoryMonitor(dir, monitorFile, this, pollIntervalMillis);
log.debug("Hot deploy scanner intialized; starting main loop.");
Thread t = new Thread(monitor, "Geronimo hot deploy scanner");
t.setDaemon(true);
@@ -466,6 +481,7 @@ public class DirectoryHotDeployer implem
GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(DirectoryHotDeployer.class);
infoFactory.addAttribute("path", String.class, true, true);
+ infoFactory.addAttribute("monitorFileName", String.class, true, true);
infoFactory.addAttribute("pollIntervalMillis", int.class, true, true);
// The next 3 args can be used to configure the hot deployer for a remote (out of VM) server
@@ -478,7 +494,7 @@ public class DirectoryHotDeployer implem
infoFactory.addAttribute("kernel", Kernel.class, false, false);
infoFactory.addInterface(HotDeployer.class);
- infoFactory.setConstructor(new String[]{"path", "pollIntervalMillis", "ServerInfo", "ConfigManager", "kernel"});
+ infoFactory.setConstructor(new String[]{"path", "monitorFileName", "pollIntervalMillis", "ServerInfo", "ConfigManager", "kernel"});
GBEAN_INFO = infoFactory.getBeanInfo();
}
Modified: geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java?rev=1090351&r1=1090350&r2=1090351&view=diff
==============================================================================
--- geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java (original)
+++ geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java Fri Apr 8 16:56:59 2011
@@ -17,7 +17,11 @@
package org.apache.geronimo.deployment.hot;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
@@ -117,13 +121,21 @@ public class DirectoryMonitor implements
private File directory;
private boolean done = false;
private Listener listener; // a little cheesy, but do we really need multiple listeners?
- private final Map<String, FileInfo> files = new HashMap<String, FileInfo>();
+ private final Map<String, FileInfo> files;
private final List<Artifact> toRemove = new ArrayList<Artifact>();
+ private File monitorFile;
public DirectoryMonitor(File directory, Listener listener, int pollIntervalMillis) {
+ this(directory, null, listener, pollIntervalMillis);
+ }
+
+ public DirectoryMonitor(File directory, File monitorFile, Listener listener, int pollIntervalMillis) {
this.directory = directory;
this.listener = listener;
this.pollIntervalMillis = pollIntervalMillis;
+ this.monitorFile = monitorFile;
+ this.files = readState();
+ persistState();
}
public int getPollIntervalMillis() {
@@ -197,6 +209,57 @@ public class DirectoryMonitor implements
}
}
+ private void persistState() {
+ if (monitorFile == null) {
+ return;
+ }
+
+ log.info("Persisting directory monitor state to " + monitorFile.getName());
+ ObjectOutputStream outputStream = null;
+ try {
+ outputStream = new ObjectOutputStream(new FileOutputStream(monitorFile));
+ outputStream.writeObject(files);
+ } catch (IOException ioe) {
+ log.warn("Error persisting directory monitor state to " + monitorFile.getName(), ioe);
+ } finally {
+ if (outputStream != null) {
+ try {
+ outputStream.close();
+ } catch (IOException ioe) {
+
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private Map<String,FileInfo> readState() {
+ Map<String,FileInfo> newFiles = null;
+ if (monitorFile != null) {
+ ObjectInputStream inputStream = null;
+ try {
+ inputStream = new ObjectInputStream(new FileInputStream(monitorFile));
+ newFiles = (Map<String,FileInfo>) inputStream.readObject();
+ } catch (IOException ex) {
+ log.info("IOException reading directory monitor state from " + monitorFile.getName(), ex);
+ } catch (ClassNotFoundException cnfe) {
+ log.warn("ClassNotFoundException reading directory monitor state from " + monitorFile.getName(), cnfe);
+ } finally {
+ try {
+ if (inputStream != null) {
+ inputStream.close();
+ }
+ } catch (IOException ioe) {
+ // ignore
+ }
+ }
+ }
+ if (newFiles == null) {
+ newFiles = new HashMap<String,FileInfo>();
+ }
+ return newFiles;
+ }
+
public void run() {
boolean serverStarted = false, initialized = false;
while (!done) {
@@ -234,6 +297,9 @@ public class DirectoryMonitor implements
if (!child.canRead()) {
continue;
}
+ if (child.equals(monitorFile)) {
+ continue;
+ }
FileInfo now = child.isDirectory() ? getDirectoryInfo(child) : getFileInfo(child);
now.setChanging(false);
try {
@@ -249,6 +315,7 @@ log.info("At startup, found "+now.getPat
log.error("Unable to scan file " + child.getAbsolutePath() + " during initialization", e);
}
}
+ persistState();
}
/**
@@ -266,16 +333,21 @@ log.info("At startup, found "+now.getPat
synchronized (files) {
Set<String> oldList = new HashSet<String>(files.keySet());
List<FileAction> actions = new LinkedList<FileAction>();
+ boolean changeMade = false;
for (int i = 0; i < children.length; i++) {
File child = children[i];
if (!child.canRead()) {
continue;
}
+ if (child.equals(monitorFile)) {
+ continue;
+ }
FileInfo now = child.isDirectory() ? getDirectoryInfo(child) : getFileInfo(child);
FileInfo then = files.get(now.getPath());
if (then == null) { // Brand new, wait a bit to make sure it's not still changing
now.setNewFile(true);
files.put(now.getPath(), now);
+ changeMade = true;
log.debug("New File: " + now.getPath());
} else {
oldList.remove(then.getPath());
@@ -296,6 +368,7 @@ log.info("At startup, found "+now.getPat
now.setConfigId(then.getConfigId());
now.setNewFile(then.isNewFile());
files.put(now.getPath(), now);
+ changeMade = true;
log.debug("File Changed: " + now.getPath());
}
}
@@ -307,6 +380,7 @@ log.info("At startup, found "+now.getPat
log.debug("File removed: " + name);
if (info.isNewFile()) { // Was never added, just whack it
files.remove(name);
+ changeMade = true;
} else {
actions.add(new FileAction(FileAction.REMOVED_FILE, new File(name), info));
}
@@ -327,6 +401,7 @@ log.info("At startup, found "+now.getPat
if (action.action == FileAction.REMOVED_FILE) {
if (action.info.getConfigId() == null || listener.fileRemoved(action.child, action.info.getConfigId())) {
files.remove(action.child.getPath());
+ changeMade = true;
}
} else if (action.action == FileAction.NEW_FILE) {
if (listener.isFileDeployed(action.child, calculateModuleId(action.child))) {
@@ -363,6 +438,7 @@ log.info("At startup, found "+now.getPat
log.error("Couldn't delete the hot deployed file="+path);
}
files.remove(path);
+ changeMade = true;
}
}
workingOnConfigId = null;
@@ -379,6 +455,7 @@ log.info("At startup, found "+now.getPat
}
}
action.info.setNewFile(false);
+ changeMade = true;
} else if (action.action == FileAction.UPDATED_FILE) {
String result = listener.fileUpdated(action.child, action.info.getConfigId());
FileInfo update = action.info;
@@ -397,6 +474,9 @@ log.info("At startup, found "+now.getPat
}
}
}
+ if (changeMade) {
+ persistState();
+ }
}
}
@@ -487,7 +567,7 @@ log.info("At startup, found "+now.getPat
}
private static class FileInfo implements Serializable {
- private String path;
+ private String path;
private long size;
private long modified;
private boolean newFile;
Modified: geronimo/server/trunk/plugins/hotdeploy/hot-deployer/src/main/plan/plan.xml
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/hotdeploy/hot-deployer/src/main/plan/plan.xml?rev=1090351&r1=1090350&r2=1090351&view=diff
==============================================================================
--- geronimo/server/trunk/plugins/hotdeploy/hot-deployer/src/main/plan/plan.xml (original)
+++ geronimo/server/trunk/plugins/hotdeploy/hot-deployer/src/main/plan/plan.xml Fri Apr 8 16:56:59 2011
@@ -28,6 +28,7 @@
<name>ConfigurationManager</name>
</reference>
<attribute name="path">deploy/</attribute>
+ <attribute name="monitorFileName">.DirectoryMonitor</attribute>
<attribute name="pollIntervalMillis">2000</attribute>
<dependency>
<name>EARBuilder</name>