incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cziege...@apache.org
Subject svn commit: r1055496 - in /sling/trunk/bundles/extensions/event: ./ src/main/java/org/apache/sling/event/impl/jobs/ src/main/java/org/apache/sling/event/impl/jobs/jcr/ src/test/java/org/apache/sling/event/impl/jobs/
Date Wed, 05 Jan 2011 15:58:43 GMT
Author: cziegeler
Date: Wed Jan  5 15:58:42 2011
New Revision: 1055496

URL: http://svn.apache.org/viewvc?rev=1055496&view=rev
Log:
SLING-1918 : Use time based folder structure for jobs without an id

Modified:
    sling/trunk/bundles/extensions/event/pom.xml
    sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/Utility.java
    sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/jcr/PersistenceHandler.java
    sling/trunk/bundles/extensions/event/src/test/java/org/apache/sling/event/impl/jobs/JobEventHandlerTest.java

Modified: sling/trunk/bundles/extensions/event/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/pom.xml?rev=1055496&r1=1055495&r2=1055496&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/pom.xml (original)
+++ sling/trunk/bundles/extensions/event/pom.xml Wed Jan  5 15:58:42 2011
@@ -170,7 +170,7 @@
         <dependency>
             <groupId>org.apache.jackrabbit</groupId>
             <artifactId>jackrabbit-jcr-commons</artifactId>
-            <version>2.0.0</version>
+            <version>2.2.0</version>
             <scope>provided</scope>
         </dependency>
       <!-- Webconsole -->
@@ -206,7 +206,7 @@
         <dependency>
             <groupId>org.apache.jackrabbit</groupId>
             <artifactId>jackrabbit-core</artifactId>
-            <version>2.0.0</version>
+            <version>2.2.0</version>
             <scope>test</scope>
         </dependency>
     </dependencies>

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/Utility.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/Utility.java?rev=1055496&r1=1055495&r2=1055496&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/Utility.java
(original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/Utility.java
Wed Jan  5 15:58:42 2011
@@ -22,11 +22,12 @@ import java.io.UnsupportedEncodingExcept
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.BitSet;
+import java.util.Calendar;
 import java.util.Dictionary;
 import java.util.Hashtable;
-import java.util.UUID;
 
 import org.apache.sling.event.impl.EnvironmentComponent;
+import org.apache.sling.event.impl.support.Environment;
 import org.apache.sling.event.jobs.JobUtil;
 import org.osgi.service.event.Event;
 import org.osgi.service.event.EventAdmin;
@@ -131,14 +132,18 @@ public abstract class Utility {
         return res.toString();
     }
 
+    /** Counter for jobs without an id.  We don't need to sync the access. */
+    private static long JOB_COUNTER = 0;
 
     /**
      * Create a unique node path (folder and name) for the job.
      */
     public static String getUniquePath(final String jobTopic, final String jobId) {
-        final StringBuilder sb = new StringBuilder(jobTopic.replace('/', '.'));
-        sb.append('/');
+        final String convTopic = jobTopic.replace('/', '.');
         if ( jobId != null ) {
+            final StringBuilder sb = new StringBuilder("identified/");
+            sb.append(convTopic);
+            sb.append('/');
             // we create an md from the job id - we use the first 6 bytes to
             // create sub directories
             final String md5 = md5(jobId);
@@ -151,23 +156,36 @@ public abstract class Utility {
             sb.append(md5.charAt(5));
             sb.append('/');
             sb.append(filter(jobId));
-        } else {
-            // create a path from the uuid - we use the first 6 bytes to
-            // create sub directories
-            final String uuid = UUID.randomUUID().toString();
-            sb.append(uuid.charAt(0));
-            sb.append(uuid.charAt(1));
-            sb.append(uuid.charAt(2));
-            sb.append('/');
-            sb.append(uuid.charAt(3));
-            sb.append(uuid.charAt(4));
-            sb.append(uuid.charAt(5));
-            sb.append("/Job_");
-            sb.append(uuid.substring(6));
+            return sb.toString();
         }
+        final Calendar now = Calendar.getInstance();
+        // create a time based path together with the Sling ID
+        final StringBuilder sb = getAnonPath(now);
+        sb.append('/');
+        sb.append(convTopic);
+        sb.append('_');
+        sb.append(JOB_COUNTER);
+        JOB_COUNTER++;
         return sb.toString();
     }
 
+    public static StringBuilder getAnonPath(final Calendar now) {
+        final StringBuilder sb = new StringBuilder("anon/");
+        // create a time based path together with the Sling ID
+        sb.append(Environment.APPLICATION_ID);
+        sb.append('/');
+        sb.append(now.get(Calendar.YEAR));
+        sb.append('/');
+        sb.append(now.get(Calendar.MONTH) + 1);
+        sb.append('/');
+        sb.append(now.get(Calendar.DAY_OF_MONTH));
+        sb.append('/');
+        sb.append(now.get(Calendar.HOUR_OF_DAY));
+        sb.append('/');
+        sb.append(now.get(Calendar.MINUTE));
+        return sb;
+    }
+
     /** Event property containing the time for job start and job finished events. */
     public static final String PROPERTY_TIME = "time";
 

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/jcr/PersistenceHandler.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/jcr/PersistenceHandler.java?rev=1055496&r1=1055495&r2=1055496&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/jcr/PersistenceHandler.java
(original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/jcr/PersistenceHandler.java
Wed Jan  5 15:58:42 2011
@@ -164,6 +164,9 @@ public class PersistenceHandler implemen
     @Reference
     private LockManager lockManager;
 
+    /** Counter for cleanups */
+    private long cleanUpCounter;
+
     /**
      * Activate this component.
      * @param context The component context.
@@ -173,6 +176,9 @@ public class PersistenceHandler implemen
         @SuppressWarnings("unchecked")
         final Dictionary<String, Object> props = context.getProperties();
         this.cleanupPeriod = OsgiUtil.toInteger(props.get(CONFIG_PROPERTY_CLEANUP_PERIOD),
DEFAULT_CLEANUP_PERIOD);
+        if ( this.cleanupPeriod < 1 ) {
+            this.cleanupPeriod = DEFAULT_CLEANUP_PERIOD;
+        }
         this.repositoryPath = OsgiUtil.toString(props.get(CONFIG_PROPERTY_REPOSITORY_PATH),
DEFAULT_REPOSITORY_PATH);
         this.running = true;
 
@@ -343,10 +349,10 @@ public class PersistenceHandler implemen
      */
     public void cleanup() {
         // remove obsolete jobs from the repository
-        if ( this.running && this.cleanupPeriod > 0 ) {
-            this.logger.debug("Cleaning up repository, removing all finished jobs older than
{} minutes.", this.cleanupPeriod);
+        if ( this.running ) {
+            this.logger.debug("Cleaning up repository: removing all finished jobs older than
{} minutes.", this.cleanupPeriod);
 
-            // we create an own session for concurrency issues
+            // we create an own session to avoid concurrency issues
             Session s = null;
             try {
                 s = this.environment.createAdminSession();
@@ -372,6 +378,157 @@ public class PersistenceHandler implemen
                     s.logout();
                 }
             }
+
+            cleanUpCounter++;
+            // we do a full cleanup every 12th run
+            if ( cleanUpCounter % 12 == 0 ) {
+                this.fullEmptyFolderCleanup();
+            } else {
+                this.simpleEmptyFolderCleanup();
+            }
+        }
+    }
+
+    /**
+     * Simple empty folder removes empty folders for the last five minutes.
+     * If folder for minute 59 is removed, we check the hour folder as well.
+     */
+    private void simpleEmptyFolderCleanup() {
+        this.logger.debug("Cleaning up repository: looking for empty folders");
+        // we create an own session to avoid concurrency issues
+        Session s = null;
+        try {
+            s = this.environment.createAdminSession();
+            final Calendar cleanUpDate = Calendar.getInstance();
+            for(int i = 0; i < 5; i++) {
+                cleanUpDate.add(Calendar.MINUTE, -1);
+                final StringBuilder sb = Utility.getAnonPath(cleanUpDate);
+
+                final String path = this.repositoryPath + '/' + sb.toString();
+
+                if ( s.nodeExists(path) ) {
+                    final Node dir = s.getNode(path);
+                    if ( !dir.hasNodes() ) {
+                        dir.remove();
+                        s.save();
+                    }
+                }
+                // check hour folder
+                if ( path.endsWith("59") ) {
+                    final String hourPath = path.substring(0, path.length() - 3);
+                    final Node hourNode = s.getNode(hourPath);
+                    if ( !hourNode.hasNodes() ) {
+                        hourNode.remove();
+                        s.save();
+                    }
+                }
+            }
+
+        } catch (RepositoryException e) {
+            // in the case of an error, we just log this as a warning
+            this.logger.warn("Exception during repository cleanup.", e);
+        } finally {
+            if ( s != null ) {
+                s.logout();
+            }
+        }
+    }
+
+    /**
+     * Full cleanup - this scans all directories!
+     */
+    private void fullEmptyFolderCleanup() {
+        this.logger.debug("Cleaning up repository: removing ALL empty folders");
+        Session s = null;
+        try {
+            s = this.environment.createAdminSession();
+
+            final String startPath = this.repositoryPath + "/anon";
+            final Node startNode = (s.nodeExists(startPath) ? s.getNode(startPath) : null);
+            if ( startNode != null ) {
+                final Calendar now = Calendar.getInstance();
+                // we iterate over the application id nodes
+                final NodeIterator idIter = startNode.getNodes();
+                while ( idIter.hasNext() ) {
+                    final Node idNode = idIter.nextNode();
+                    // now years
+                    final NodeIterator yearIter = idNode.getNodes();
+                    while ( yearIter.hasNext() ) {
+                        final Node yearNode = yearIter.nextNode();
+                        final int year = Integer.valueOf(yearNode.getName());
+                        final boolean oldYear = year < now.get(Calendar.YEAR);
+
+                        // months
+                        final NodeIterator monthIter = yearNode.getNodes();
+                        while ( monthIter.hasNext() ) {
+                            final Node monthNode = monthIter.nextNode();
+                            final int month = Integer.valueOf(monthNode.getName());
+                            final boolean oldMonth = oldYear || month < (now.get(Calendar.MONTH)
+ 1);
+
+                            // days
+                            final NodeIterator dayIter = monthNode.getNodes();
+                            while ( dayIter.hasNext() ) {
+                                final Node dayNode = dayIter.nextNode();
+                                final int day = Integer.valueOf(dayNode.getName());
+                                final boolean oldDay = oldMonth || day < now.get(Calendar.DAY_OF_MONTH);
+
+                                // hours
+                                final NodeIterator hourIter = dayNode.getNodes();
+                                while ( hourIter.hasNext() ) {
+                                    final Node hourNode = hourIter.nextNode();
+                                    final int hour = Integer.valueOf(hourNode.getName());
+                                    final boolean oldHour = oldDay || hour < now.get(Calendar.HOUR);
+
+                                    // minutes
+                                    final NodeIterator minuteIter = hourNode.getNodes();
+                                    while ( minuteIter.hasNext() ) {
+                                        final Node minuteNode = minuteIter.nextNode();
+                                        final int minute = Integer.valueOf(minuteNode.getName());
+                                        final boolean oldMinute = oldHour || minute <
now.get(Calendar.MINUTE);
+
+                                        // check if we can delete the minute
+                                        if ( oldMinute && !minuteNode.hasNodes())
{
+                                            minuteNode.remove();
+                                            s.save();
+                                        }
+                                    }
+
+                                    // check if we can delete the hour
+                                    if ( oldHour && !hourNode.hasNodes()) {
+                                        hourNode.remove();
+                                        s.save();
+                                    }
+                                }
+                                // check if we can delete the day
+                                if ( oldDay && !dayNode.hasNodes()) {
+                                    dayNode.remove();
+                                    s.save();
+                                }
+                            }
+
+                            // check if we can delete the month
+                            if ( oldMonth && !monthNode.hasNodes() ) {
+                                monthNode.remove();
+                                s.save();
+                            }
+                        }
+
+                        // check if we can delete the year
+                        if ( oldYear && !yearNode.hasNodes() ) {
+                            yearNode.remove();
+                            s.save();
+                        }
+                    }
+                }
+            }
+
+        } catch (RepositoryException e) {
+            // in the case of an error, we just log this as a warning
+            this.logger.warn("Exception during repository cleanup.", e);
+        } finally {
+            if ( s != null ) {
+                s.logout();
+            }
         }
     }
 
@@ -1093,7 +1250,7 @@ public class PersistenceHandler implemen
                             node.getSession().save();
                         } catch (RepositoryException re) {
                             // we ignore this as this folder might be created from a different
task
-                            node.refresh(false);
+                            node.getSession().refresh(false);
                         }
                     }
                     node = node.getNode(token);

Modified: sling/trunk/bundles/extensions/event/src/test/java/org/apache/sling/event/impl/jobs/JobEventHandlerTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/test/java/org/apache/sling/event/impl/jobs/JobEventHandlerTest.java?rev=1055496&r1=1055495&r2=1055496&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/test/java/org/apache/sling/event/impl/jobs/JobEventHandlerTest.java
(original)
+++ sling/trunk/bundles/extensions/event/src/test/java/org/apache/sling/event/impl/jobs/JobEventHandlerTest.java
Wed Jan  5 15:58:42 2011
@@ -470,7 +470,8 @@ public class JobEventHandlerTest extends
         writeEvent(null, "8");
 
         RepositoryTestUtil.getAdminSession().save();
-        assertEquals(obsolete, RepositoryTestUtil.getAdminSession().getNode(REPO_PATH).getNode("1").getProperty(JCRHelper.NODE_PROPERTY_FINISHED).getDate());
+        assertEquals(obsolete.getTimeInMillis(),
+                     RepositoryTestUtil.getAdminSession().getNode(REPO_PATH).getNode("1").getProperty(JCRHelper.NODE_PROPERTY_FINISHED).getDate().getTimeInMillis());
         assertTrue(RepositoryTestUtil.getAdminSession().getNode(REPO_PATH).hasNode("2"));
         assertTrue(RepositoryTestUtil.getAdminSession().getNode(REPO_PATH).hasNode("3"));
         assertTrue(RepositoryTestUtil.getAdminSession().getNode(REPO_PATH).hasNode("4"));



Mime
View raw message