Author: kwright
Date: Sun Aug 12 16:26:04 2012
New Revision: 1372143

URL: http://svn.apache.org/viewvc?rev=1372143&view=rev
Log:
Finish hopcountremoval state addition.

Modified:
    
manifoldcf/branches/CONNECTORS-501/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/interfaces/IJobManager.java
    
manifoldcf/branches/CONNECTORS-501/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/jobs/JobManager.java
    
manifoldcf/branches/CONNECTORS-501/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/jobs/JobQueue.java
    
manifoldcf/branches/CONNECTORS-501/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/WorkerThread.java
    
manifoldcf/branches/CONNECTORS-501/tests/webcrawler/src/test/java/org/apache/manifoldcf/webcrawler_tests/MockWebService.java

Modified: 
manifoldcf/branches/CONNECTORS-501/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/interfaces/IJobManager.java
URL: 
http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-501/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/interfaces/IJobManager.java?rev=1372143&r1=1372142&r2=1372143&view=diff
==============================================================================
--- 
manifoldcf/branches/CONNECTORS-501/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/interfaces/IJobManager.java
 (original)
+++ 
manifoldcf/branches/CONNECTORS-501/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/interfaces/IJobManager.java
 Sun Aug 12 16:26:04 2012
@@ -302,6 +302,34 @@ public interface IJobManager
     int hopcountMethod)
     throws ManifoldCFException;
 
+  /** Mark hopcount removal from queue as a result of processing of an active 
document.
+  * The document is expected to be in one of the active states: ACTIVE, 
ACTIVESEEDING,
+  * ACTIVENEEDSRESCAN, ACTIVESEEDINGNEEDSRESCAN.  The RESCAN variants are 
interpreted
+  * as meaning that the document should not be marked as removed, but should 
instead be popped back on the queue for
+  * a repeat processing attempt.
+  *@param documentDescriptions are the set of description objects for the 
documents that were processed.
+  *@param hopcountMethod describes how to handle deletions for hopcount 
purposes.
+  *@return the set of documents for which carrydown data was changed by this 
operation.  These documents are likely
+  *  to be requeued as a result of the change.
+  */
+  public DocumentDescription[] markDocumentHopcountRemovalMultiple(Long jobID, 
String[] legalLinkTypes, DocumentDescription[] documentDescriptions,
+    int hopcountMethod)
+    throws ManifoldCFException;
+
+  /** Mark hopcount removal from queue as a result of processing of an active 
document.
+  * The document is expected to be in one of the active states: ACTIVE, 
ACTIVESEEDING,
+  * ACTIVENEEDSRESCAN, ACTIVESEEDINGNEEDSRESCAN.  The RESCAN variants are 
interpreted
+  * as meaning that the document should not be marked as removed, but should 
instead be popped back on the queue for
+  * a repeat processing attempt.
+  *@param documentDescription is the description object for the document that 
was processed.
+  *@param hopcountMethod describes how to handle deletions for hopcount 
purposes.
+  *@return the set of documents for which carrydown data was changed by this 
operation.  These documents are likely
+  *  to be requeued as a result of the change.
+  */
+  public DocumentDescription[] markDocumentHopcountRemoval(Long jobID, 
String[] legalLinkTypes, DocumentDescription documentDescription,
+    int hopcountMethod)
+    throws ManifoldCFException;
+
   /** Delete from queue as a result of expiration of an active document.
   * The document is expected to be in one of the active states: ACTIVE, 
ACTIVESEEDING,
   * ACTIVENEEDSRESCAN, ACTIVESEEDINGNEEDSRESCAN.  Since the document expired,

Modified: 
manifoldcf/branches/CONNECTORS-501/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/jobs/JobManager.java
URL: 
http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-501/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/jobs/JobManager.java?rev=1372143&r1=1372142&r2=1372143&view=diff
==============================================================================
--- 
manifoldcf/branches/CONNECTORS-501/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/jobs/JobManager.java
 (original)
+++ 
manifoldcf/branches/CONNECTORS-501/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/jobs/JobManager.java
 Sun Aug 12 16:26:04 2012
@@ -2613,6 +2613,144 @@ public class JobManager implements IJobM
     return markDocumentDeletedMultiple(jobID,legalLinkTypes,new 
DocumentDescription[]{documentDescription},hopcountMethod);
   }
 
+  /** Mark hopcount removal from queue as a result of processing of an active 
document.
+  * The document is expected to be in one of the active states: ACTIVE, 
ACTIVESEEDING,
+  * ACTIVENEEDSRESCAN, ACTIVESEEDINGNEEDSRESCAN.  The RESCAN variants are 
interpreted
+  * as meaning that the document should not be marked as removed, but should 
instead be popped back on the queue for
+  * a repeat processing attempt.
+  *@param documentDescriptions are the set of description objects for the 
documents that were processed.
+  *@param hopcountMethod describes how to handle deletions for hopcount 
purposes.
+  *@return the set of documents for which carrydown data was changed by this 
operation.  These documents are likely
+  *  to be requeued as a result of the change.
+  */
+  public DocumentDescription[] markDocumentHopcountRemovalMultiple(Long jobID, 
String[] legalLinkTypes, DocumentDescription[] documentDescriptions,
+    int hopcountMethod)
+    throws ManifoldCFException
+  {
+    // For each record, we're going to have to choose between marking it as 
"hopcount removed", and marking
+    // it for rescan.  So the basic flow will involve changing a document's 
status,.
+    
+    // Before we can change a document status, we need to know the *current* 
status.  Therefore, a SELECT xxx FOR UPDATE/UPDATE
+    // transaction is needed in order to complete these documents correctly.
+    //
+    // Since we are therefore setting row locks on thejobqueue table, we need 
to work to avoid unnecessary deadlocking.  To do that, we have to
+    // lock rows in document id hash order!!  Luckily, the DocumentDescription 
objects have a document identifier buried within, which we can use to
+    // order the "select for update" operations appropriately.
+    //
+
+    HashMap indexMap = new HashMap();
+    String[] docIDHashes = new String[documentDescriptions.length];
+
+    int i = 0;
+    while (i < documentDescriptions.length)
+    {
+      String documentIDHash = 
documentDescriptions[i].getDocumentIdentifierHash() + ":" + 
documentDescriptions[i].getJobID();
+      docIDHashes[i] = documentIDHash;
+      indexMap.put(documentIDHash,new Integer(i));
+      i++;
+    }
+
+    java.util.Arrays.sort(docIDHashes);
+
+    // Retry loop - in case we get a deadlock despite our best efforts
+    while (true)
+    {
+      long sleepAmt = 0L;
+      database.beginTransaction(database.TRANSACTION_SERIALIZED);
+      try
+      {
+        // Do one row at a time, to avoid deadlocking things
+        List<String> deleteList = new ArrayList<String>();
+        
+        i = 0;
+        while (i < docIDHashes.length)
+        {
+          String docIDHash = docIDHashes[i];
+
+          // Get the DocumentDescription object
+          DocumentDescription dd = 
documentDescriptions[((Integer)indexMap.get(docIDHash)).intValue()];
+
+          // Query for the status
+          ArrayList list = new ArrayList();
+          String query = database.buildConjunctionClause(list,new 
ClauseDescription[]{
+            new UnitaryClause(jobQueue.idField,dd.getID())});
+          IResultSet set = database.performQuery("SELECT 
"+jobQueue.statusField+" FROM "+jobQueue.getTableName()+" WHERE "+
+            query+" FOR UPDATE",list,null,null);
+          if (set.getRowCount() > 0)
+          {
+            IResultRow row = set.getRow(0);
+            // Grab the status
+            int status = 
jobQueue.stringToStatus((String)row.getValue(jobQueue.statusField));
+            // Update the jobqueue table
+            boolean didDelete = 
jobQueue.updateOrHopcountRemoveRecord(dd.getID(),status);
+            if (didDelete)
+            {
+              deleteList.add(dd.getDocumentIdentifierHash());
+            }
+          }
+          i++;
+        }
+        
+        String[] docIDSimpleHashes = new String[deleteList.size()];
+        for (int j = 0; j < docIDSimpleHashes.length; j++)
+        {
+          docIDSimpleHashes[j] = deleteList.get(j);
+        }
+        
+        // Next, find the documents that are affected by carrydown deletion.
+        DocumentDescription[] rval = 
calculateAffectedDeleteCarrydownChildren(jobID,docIDSimpleHashes);
+
+        // Finally, delete the carrydown records in question.
+        carryDown.deleteRecords(jobID,docIDSimpleHashes);
+        if (legalLinkTypes.length > 0)
+          
hopCount.deleteDocumentIdentifiers(jobID,legalLinkTypes,docIDSimpleHashes,hopcountMethod);
+
+        database.performCommit();
+        return rval;
+      }
+      catch (ManifoldCFException e)
+      {
+        database.signalRollback();
+        if (e.getErrorCode() == e.DATABASE_TRANSACTION_ABORT)
+        {
+          if (Logging.perf.isDebugEnabled())
+            Logging.perf.debug("Aborted transaction marking completed 
"+Integer.toString(docIDHashes.length)+
+            " docs: "+e.getMessage());
+          sleepAmt = getRandomAmount();
+          continue;
+        }
+        throw e;
+      }
+      catch (Error e)
+      {
+        database.signalRollback();
+        throw e;
+      }
+      finally
+      {
+        database.endTransaction();
+        sleepFor(sleepAmt);
+      }
+    }
+  }
+
+  /** Mark hopcount removal from queue as a result of processing of an active 
document.
+  * The document is expected to be in one of the active states: ACTIVE, 
ACTIVESEEDING,
+  * ACTIVENEEDSRESCAN, ACTIVESEEDINGNEEDSRESCAN.  The RESCAN variants are 
interpreted
+  * as meaning that the document should not be marked as removed, but should 
instead be popped back on the queue for
+  * a repeat processing attempt.
+  *@param documentDescription is the description object for the document that 
was processed.
+  *@param hopcountMethod describes how to handle deletions for hopcount 
purposes.
+  *@return the set of documents for which carrydown data was changed by this 
operation.  These documents are likely
+  *  to be requeued as a result of the change.
+  */
+  public DocumentDescription[] markDocumentHopcountRemoval(Long jobID, 
String[] legalLinkTypes, DocumentDescription documentDescription,
+    int hopcountMethod)
+    throws ManifoldCFException
+  {
+    return markDocumentHopcountRemovalMultiple(jobID,legalLinkTypes,new 
DocumentDescription[]{documentDescription},hopcountMethod);
+  }
+
   /** Delete from queue as a result of expiration of an active document.
   * The document is expected to be in one of the active states: ACTIVE, 
ACTIVESEEDING,
   * ACTIVENEEDSRESCAN, ACTIVESEEDINGNEEDSRESCAN.  Since the document expired,

Modified: 
manifoldcf/branches/CONNECTORS-501/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/jobs/JobQueue.java
URL: 
http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-501/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/jobs/JobQueue.java?rev=1372143&r1=1372142&r2=1372143&view=diff
==============================================================================
--- 
manifoldcf/branches/CONNECTORS-501/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/jobs/JobQueue.java
 (original)
+++ 
manifoldcf/branches/CONNECTORS-501/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/jobs/JobQueue.java
 Sun Aug 12 16:26:04 2012
@@ -759,6 +759,54 @@ public class JobQueue extends org.apache
     return false;
   }
 
+  /** Either mark a record as hopcountremoved, or set status to "rescan", 
depending on the
+  * record's state.
+  */
+  public boolean updateOrHopcountRemoveRecord(Long recID, int currentStatus)
+    throws ManifoldCFException
+  {
+    HashMap map = new HashMap();
+    
+    int newStatus;
+    String actionFieldValue;
+    Long checkTimeValue;
+    
+    boolean rval;
+    
+    switch (currentStatus)
+    {
+    case STATUS_ACTIVE:
+    case STATUS_ACTIVEPURGATORY:
+      // Mark as hopcountremove
+      newStatus = STATUS_HOPCOUNTREMOVED;
+      actionFieldValue = actionToString(ACTION_RESCAN);
+      checkTimeValue = new Long(0L);
+      rval = true;
+      break;
+    case STATUS_ACTIVENEEDRESCAN:
+    case STATUS_ACTIVENEEDRESCANPURGATORY:
+      newStatus = STATUS_PENDINGPURGATORY;
+      actionFieldValue = actionToString(ACTION_RESCAN);
+      checkTimeValue = new Long(0L);
+      rval = false;
+      // Leave doc priority unchanged.
+      break;
+    default:
+      throw new ManifoldCFException("Unexpected jobqueue status - record id 
"+recID.toString()+", expecting active status, saw 
"+Integer.toString(currentStatus));
+    }
+
+    map.put(statusField,statusToString(newStatus));
+    map.put(checkTimeField,checkTimeValue);
+    map.put(checkActionField,actionFieldValue);
+    map.put(failTimeField,null);
+    map.put(failCountField,null);
+    ArrayList list = new ArrayList();
+    String query = buildConjunctionClause(list,new ClauseDescription[]{
+      new UnitaryClause(idField,recID)});
+    performUpdate(map,"WHERE "+query,list,null);
+    return rval;
+  }
+
   /** Set the status to active on a record, leaving alone priority or check 
time.
   *@param id is the job queue id.
   *@param currentStatus is the current status


Reply via email to