SLING-3747 - Provide a way to signal Jcr Installer to pause and resume scanning
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1617254 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrInstaller.java b/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrInstaller.java
index a7b346b..3077258 100644
--- a/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrInstaller.java
+++ b/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrInstaller.java
@@ -178,6 +178,15 @@
/** The path for new configurations. */
private String newConfigPath;
+ public static final String PAUSE_SCAN_NODE_PATH = "/system/sling/installer/jcr/pauseInstallation";
+ @Property(value= PAUSE_SCAN_NODE_PATH)
+ private static final String PROP_SCAN_PROP_PATH = "sling.jcrinstall.signal.path";
+
+ /** The path for pauseInstallation property */
+ private String pauseScanNodePath;
+
+ private volatile boolean pauseMessageLogged = false;
+
private static final boolean DEFAULT_ENABLE_WRITEBACK = true;
@Property(boolValue=DEFAULT_ENABLE_WRITEBACK)
private static final String PROP_ENABLE_WRITEBACK = "sling.jcrinstall.enable.writeback";
@@ -360,6 +369,8 @@
this.newConfigPath = this.folderNameFilter.getRootPaths()[0] + '/' + this.newConfigPath;
}
+ this.pauseScanNodePath = PropertiesUtil.toString(getPropertyValue(PROP_SCAN_PROP_PATH), PAUSE_SCAN_NODE_PATH);
+
backgroundThread = new StoppableThread();
backgroundThread.start();
}
@@ -593,6 +604,22 @@
try {
boolean didRefresh = false;
+ if (anyWatchFolderNeedsScan()) {
+ session.refresh(false);
+ didRefresh = true;
+ if (scanningIsPaused()) {
+ if (!pauseMessageLogged) {
+ //Avoid flooding the logs every 500 msec so log at info level once
+ logger.info("Detected signal for pausing the JCR Provider i.e. child nodes found under path {}. " +
+ "JCR Provider scanning would not be performed", pauseScanNodePath);
+ pauseMessageLogged = true;
+ }
+ return;
+ } else if (pauseMessageLogged) {
+ pauseMessageLogged = false;
+ }
+ }
+
// Rescan WatchedFolders if needed
boolean scanWf = false;
for(WatchedFolder wf : watchedFolders) {
@@ -651,6 +678,32 @@
counters[RUN_LOOP_COUNTER]++;
}
+ boolean scanningIsPaused() throws RepositoryException {
+ if (session.nodeExists(pauseScanNodePath)) {
+ Node node = session.getNode(pauseScanNodePath);
+ boolean result = node.hasNodes();
+ if (result && logger.isDebugEnabled()) {
+ List<String> nodeNames = new ArrayList<String>();
+ NodeIterator childItr = node.getNodes();
+ while (childItr.hasNext()) {
+ nodeNames.add(childItr.nextNode().getName());
+ }
+ logger.debug("Found child nodes {} at path {}. Scanning would be paused", nodeNames, pauseScanNodePath);
+ }
+ return result;
+ }
+ return false;
+ }
+
+ private boolean anyWatchFolderNeedsScan() {
+ for (WatchedFolder wf : watchedFolders) {
+ if (wf.needsScan()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
long [] getCounters() {
return counters;
}
diff --git a/src/main/resources/OSGI-INF/metatype/metatype.properties b/src/main/resources/OSGI-INF/metatype/metatype.properties
index 0334971..d04e307 100644
--- a/src/main/resources/OSGI-INF/metatype/metatype.properties
+++ b/src/main/resources/OSGI-INF/metatype/metatype.properties
@@ -33,7 +33,7 @@
sling.jcrinstall.folder.name.regexp.name = Installation folders name regexp
sling.jcrinstall.folder.name.regexp.description = JCRInstall looks in repository folders \
- having a name that match this regular expression (under the root paths, which are defined \
+ having a name that match this regular expression (under the root paths, which are defined \
by the ResourceResolver search path) for resources to install. Folders having names \
that match this expression, followed by dotted run mode selectors (like "install.author.production") \
are also included.
@@ -58,4 +58,9 @@
handler.schemes.description = For these schemes this installer writes back configurations.
service.ranking.name = Ranking
-service.ranking.description = Ranking of this service.
\ No newline at end of file
+service.ranking.description = Ranking of this service.
+
+sling.jcrinstall.signal.path.name = Signal Node Path
+sling.jcrinstall.signal.path.description = Path of the node in repository whose children would be \
+ watched for determining if the watch folder scanning has to be performed or not. If any child node is found \
+ at this path then scanning would be paused.
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/installer/provider/jcr/impl/ContentHelper.java b/src/test/java/org/apache/sling/installer/provider/jcr/impl/ContentHelper.java
index e10e07c..9bc8764 100644
--- a/src/test/java/org/apache/sling/installer/provider/jcr/impl/ContentHelper.java
+++ b/src/test/java/org/apache/sling/installer/provider/jcr/impl/ContentHelper.java
@@ -112,7 +112,7 @@
}
}
- void createFolder(String path) throws Exception {
+ Node createFolder(String path) throws Exception {
final String [] parts = relPath(path).split("/");
Node n = session.getRootNode();
for(String part : parts) {
@@ -123,6 +123,7 @@
}
}
session.save();
+ return n;
}
void delete(String path) throws RepositoryException {
diff --git a/src/test/java/org/apache/sling/installer/provider/jcr/impl/ScanningLoopTest.java b/src/test/java/org/apache/sling/installer/provider/jcr/impl/ScanningLoopTest.java
index b0076b6..3211ab8 100644
--- a/src/test/java/org/apache/sling/installer/provider/jcr/impl/ScanningLoopTest.java
+++ b/src/test/java/org/apache/sling/installer/provider/jcr/impl/ScanningLoopTest.java
@@ -18,11 +18,12 @@
*/
package org.apache.sling.installer.provider.jcr.impl;
+
+import javax.jcr.Node;
import javax.jcr.Session;
import org.apache.sling.commons.testing.jcr.EventHelper;
import org.apache.sling.commons.testing.jcr.RepositoryTestBase;
-import org.apache.sling.installer.provider.jcr.impl.JcrInstaller;
import org.apache.sling.jcr.api.SlingRepository;
import org.junit.Test;
@@ -56,6 +57,7 @@
MiscUtil.waitForInstallerThread(installer, TIMEOUT);
installer = null;
contentHelper.cleanupContent();
+ contentHelper.deleteQuietly(JcrInstaller.PAUSE_SCAN_NODE_PATH);
if(session != null) {
session.logout();
session = null;
@@ -85,6 +87,38 @@
assertIdle();
}
+ public void testDefaultScanPauseFalse() throws Exception{
+ assertFalse(installer.scanningIsPaused());
+ }
+
+ public void testPauseScan() throws Exception{
+ assertFalse(installer.scanningIsPaused());
+
+ Node n = contentHelper.createFolder(JcrInstaller.PAUSE_SCAN_NODE_PATH);
+ Node testNode = n.addNode("foo.example.pause");
+ session.save();
+
+ eventHelper.waitForEvents(TIMEOUT);
+
+ assertTrue(installer.scanningIsPaused());
+ final long sf = installer.getCounters()[JcrInstaller.SCAN_FOLDERS_COUNTER];
+ final long uc = installer.getCounters()[JcrInstaller.UPDATE_FOLDERS_LIST_COUNTER];
+
+ Thread.sleep(JcrInstaller.RUN_LOOP_DELAY_MSEC * 2);
+
+ //Counters should not have changed as no scanning being performed
+ assertEquals(sf, installer.getCounters()[JcrInstaller.SCAN_FOLDERS_COUNTER]);
+
+ //Now lets resume again
+ testNode.remove();
+ session.save();
+
+ Thread.sleep(JcrInstaller.RUN_LOOP_DELAY_MSEC * 2);
+
+ //Now counters should have changed
+ assertIdle();
+ }
+
@Test
public void testAddBundle() throws Exception {
contentHelper.createOrUpdateFile(contentHelper.FAKE_RESOURCES[0]);
@@ -137,4 +171,9 @@
assertIdle();
}
+
+ private static String getParentPath(String absPath){
+ int pos = absPath.lastIndexOf('/');
+ return absPath.substring(0, pos);
+ }
}
\ No newline at end of file