]> source.dussan.org Git - archiva.git/commitdiff
[MRM-77] run report in the background
authorBrett Porter <brett@apache.org>
Sat, 9 Sep 2006 08:08:37 +0000 (08:08 +0000)
committerBrett Porter <brett@apache.org>
Sat, 9 Sep 2006 08:08:37 +0000 (08:08 +0000)
git-svn-id: https://svn.apache.org/repos/asf/maven/archiva/trunk@441757 13f79535-47bb-0310-9956-ffa450edef68

archiva-core/src/main/java/org/apache/maven/archiva/scheduler/task/IndexerTask.java
archiva-reports-standard/src/main/java/org/apache/maven/archiva/reporting/DefaultReportExecutor.java
archiva-reports-standard/src/main/java/org/apache/maven/archiva/reporting/DefaultReportingStore.java
archiva-reports-standard/src/main/java/org/apache/maven/archiva/reporting/ReportExecutor.java
archiva-reports-standard/src/main/java/org/apache/maven/archiva/reporting/ReportingDatabase.java
archiva-reports-standard/src/main/java/org/apache/maven/archiva/reporting/ReportingStore.java
archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/ReportsAction.java
archiva-webapp/src/main/resources/xwork.xml
archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/reports.jsp

index 75280b3eaa5142bd6209664c17736a0366a774c5..b556e15b59a485480c6acd4550056f462bae18e8 100644 (file)
@@ -182,6 +182,8 @@ public class IndexerTask
                             List currentArtifacts =
                                 artifacts.subList( j, end > artifacts.size() ? artifacts.size() : end );
 
+                            // TODO: proper queueing of this in case it was triggered externally (not harmful to do so at present, but not optimal)
+
                             // run the reports. Done intermittently to avoid losing track of what is indexed since
                             // that is what the filter is based on.
                             reportExecutor.runArtifactReports( currentArtifacts, repository );
index 4e73d58b59733cb82db32ff8502d8dcd379aba6d..08a5e89bf5e81270356fe2fa1a783363891eec56 100644 (file)
@@ -85,6 +85,8 @@ public class DefaultReportExecutor
      */
     private Map metadataDiscoverers;
 
+    private static final int ARTIFACT_BUFFER_SIZE = 1000;
+
     public void runMetadataReports( List metadata, ArtifactRepository repository )
         throws ReportingStoreException
     {
@@ -160,7 +162,8 @@ public class DefaultReportExecutor
         throws DiscovererException, ReportingStoreException
     {
         // Flush (as in toilet, not store) the report database
-        reportingStore.removeReportDatabase( repository );
+        ReportingDatabase database = getReportDatabase( repository );
+        database.clear();
 
         // Discovery process
         String layoutProperty = getRepositoryLayout( repository.getLayout() );
@@ -176,8 +179,21 @@ public class DefaultReportExecutor
         {
             getLogger().info( "Discovered " + artifacts.size() + " artifacts" );
 
-            // run the reports
-            runArtifactReports( artifacts, repository );
+            // Work through these in batches, then flush the project cache.
+            for ( int j = 0; j < artifacts.size(); j += ARTIFACT_BUFFER_SIZE )
+            {
+                int end = j + ARTIFACT_BUFFER_SIZE;
+                List currentArtifacts = artifacts.subList( j, end > artifacts.size() ? artifacts.size() : end );
+
+                // TODO: proper queueing of this in case it was triggered externally (not harmful to do so at present, but not optimal)
+
+                // run the reports.
+                runArtifactReports( currentArtifacts, repository );
+            }
+
+            // MNG-142 - the project builder retains a lot of objects in its inflexible cache. This is a hack
+            // around that. TODO: remove when it is configurable
+            flushProjectBuilderCacheHack();
         }
 
         MetadataDiscoverer metadataDiscoverer = (MetadataDiscoverer) metadataDiscoverers.get( layoutProperty );
@@ -220,4 +236,31 @@ public class DefaultReportExecutor
             report.processArtifact( artifact, model, reporter );
         }
     }
+
+    private void flushProjectBuilderCacheHack()
+    {
+        try
+        {
+            if ( projectBuilder != null )
+            {
+                java.lang.reflect.Field f = projectBuilder.getClass().getDeclaredField( "rawProjectCache" );
+                f.setAccessible( true );
+                Map cache = (Map) f.get( projectBuilder );
+                cache.clear();
+
+                f = projectBuilder.getClass().getDeclaredField( "processedProjectCache" );
+                f.setAccessible( true );
+                cache = (Map) f.get( projectBuilder );
+                cache.clear();
+            }
+        }
+        catch ( NoSuchFieldException e )
+        {
+            throw new RuntimeException( e );
+        }
+        catch ( IllegalAccessException e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
 }
index b61b1227717c0ba0bb99c888570ed68dda2b4b4b..8d033e2e0927a981665d21f7f478ea2b270f012a 100644 (file)
@@ -121,8 +121,4 @@ public class DefaultReportingStore
         }
     }
 
-    public void removeReportDatabase( ArtifactRepository repository )
-    {
-        reports.remove( repository );
-    }
 }
index c20c10c8c23c95f37a923ef59c093e7ab8179822..39aedd8d19da8c7ba6175f54081c75893755efab 100644 (file)
@@ -68,6 +68,9 @@ public interface ReportExecutor
      * @param repository          the repository to run from
      * @param blacklistedPatterns the patterns to exclude during discovery
      * @param filter              the filter to use during discovery to get a consistent list of artifacts
+     * @throws ReportingStoreException if there is a problem reading/writing the report database
+     * @throws org.apache.maven.archiva.discoverer.DiscovererException
+     *                                 if there is a problem finding the artifacts and metadata to report on
      */
     public void runReports( ArtifactRepository repository, List blacklistedPatterns, ArtifactFilter filter )
         throws DiscovererException, ReportingStoreException;
index de6aebf7d892519a64a08256f1bdf286b8753e3c..ba6ad5bf8b0839a915b04002a82309ed409bc0c2 100644 (file)
@@ -45,6 +45,8 @@ public class ReportingDatabase
 
     private ArtifactRepository repository;
 
+    private boolean inProgress;
+
     public ReportingDatabase()
     {
         this( new Reporting(), null );
@@ -279,4 +281,26 @@ public class ReportingDatabase
         return repository;
     }
 
+    public boolean isInProgress()
+    {
+        return inProgress;
+    }
+
+    public void setInProgress( boolean inProgress )
+    {
+        this.inProgress = inProgress;
+    }
+
+    public void clear()
+    {
+        // clear the values rather than destroy the instance so that the "inProgress" indicator is in tact.
+        numWarnings = 0;
+        numFailures = 0;
+
+        artifactMap.clear();
+        metadataMap.clear();
+
+        reporting.getArtifacts().clear();
+        reporting.getMetadata().clear();
+    }
 }
index f37c41e7c675f332a58b11de5c5e594b80aec163..00d9b7c140c5d5e6d73c17fe2fc5796873829244 100644 (file)
@@ -51,10 +51,4 @@ public interface ReportingStore
     void storeReports( ReportingDatabase database, ArtifactRepository repository )
         throws ReportingStoreException;
 
-    /**
-     * Remove the report database from the memory cache.
-     *
-     * @param repository the repository of the database to remove
-     */
-    void removeReportDatabase( ArtifactRepository repository );
 }
index c4a77f365f286e6519e486e05bc2a9a984563bbe..79f84a0852d73d0bd96bcdf26b8e51d00a65bdcc 100644 (file)
@@ -95,6 +95,14 @@ public class ReportsAction
         RepositoryConfiguration repositoryConfiguration = configuration.getRepositoryById( repositoryId );
         ArtifactRepository repository = factory.createRepository( repositoryConfiguration );
 
+        ReportingDatabase database = executor.getReportDatabase( repository );
+        if ( database.isInProgress() )
+        {
+            return SUCCESS;
+        }
+
+        database.setInProgress( true );
+
         List blacklistedPatterns = new ArrayList();
         if ( repositoryConfiguration.getBlackListPatterns() != null )
         {
@@ -115,9 +123,16 @@ public class ReportsAction
             filter = new SnapshotArtifactFilter();
         }
 
-        executor.runReports( repository, blacklistedPatterns, filter );
+        try
+        {
+            executor.runReports( repository, blacklistedPatterns, filter );
+        }
+        finally
+        {
+            database.setInProgress( false );
+        }
 
-        return execute();
+        return SUCCESS;
     }
 
     public String getRepositoryId()
index 61def7a32360937bde410e8097b4d3fa2f4e1c8a..ea61ccb8636603230d4787c7b16e8fba679c6c07 100644 (file)
       <result>/WEB-INF/jsp/reports/reports.jsp</result>
     </action>
 
+    <action name="runReport" class="reportsAction" method="runReport">
+      <interceptor-ref name="configuredStack"/>
+      <interceptor-ref name="execAndWait"/>
+      <result name="wait" type="redirect-action">reports</result>
+      <result name="success" type="redirect-action">reports</result>
+    </action>
+
     <action name="showArtifactDependencies" class="showArtifactAction" method="dependencies">
       <result>/WEB-INF/jsp/showArtifact.jsp</result>
     </action>
index 9bc3713b01e79ecf9a82c252d54fcff343e2647c..523f05b9611c23c8f951c6a2584fe82958a3de2e 100644 (file)
@@ -30,6 +30,8 @@
 
 <div id="contentArea">
 
+<ww:actionerror/>
+
 <ww:set name="databases" value="databases"/>
 <c:forEach items="${databases}" var="database">
 <div>
   <a href="#">Repair all</a>
   |
     --%>
-  <c:set var="url">
-    <ww:url action="reports" namespace="/" method="runReport">
-      <ww:param name="repositoryId" value="%{'${database.repository.id}'}"/>
-    </ww:url>
-  </c:set>
-  <a href="${url}">Regenerate Report</a>
+  <c:choose>
+    <c:when test="${!database.inProgress}">
+      <c:set var="url">
+        <ww:url action="runReport" namespace="/">
+          <ww:param name="repositoryId" value="%{'${database.repository.id}'}"/>
+        </ww:url>
+      </c:set>
+      <a href="${url}">Regenerate Report</a>
+    </c:when>
+    <c:otherwise>
+      <!-- TODO: would be good to have a generic task/job mechanism that tracked progress and ability to run
+      concurrently -->
+      <span style="color: gray;">Report in progress</span>
+    </c:otherwise>
+  </c:choose>
 </div>
 <h2>Repository: ${database.repository.name}</h2>
 
@@ -55,8 +66,9 @@
     ${database.numWarnings}
 </p>
 
+  <%-- TODO need to protect iterations against concurrent modification exceptions by cloning the lists synchronously --%>
   <%-- TODO! factor out common parts, especially artifact rendering tag --%>
-  <%-- TODO! paginate --%>
+  <%-- TODO! paginate (displaytag?) --%>
 <c:if test="${!empty(database.reporting.artifacts)}">
   <h3>Artifacts</h3>
   <c:forEach items="${database.reporting.artifacts}" var="artifact" begin="0" end="2">