Author: kwright
Date: Wed Nov 27 11:16:27 2013
New Revision: 1545996

URL: http://svn.apache.org/r1545996
Log:
Move document prioritization to docbins table, and out of QueueTracker.

Modified:
    
manifoldcf/branches/CONNECTORS-781/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/bins/BinManager.java
    
manifoldcf/branches/CONNECTORS-781/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/interfaces/QueueTracker.java
    
manifoldcf/branches/CONNECTORS-781/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/ManifoldCF.java
    
manifoldcf/branches/CONNECTORS-781/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/PriorityCalculator.java

Modified: 
manifoldcf/branches/CONNECTORS-781/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/bins/BinManager.java
URL: 
http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-781/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/bins/BinManager.java?rev=1545996&r1=1545995&r2=1545996&view=diff
==============================================================================
--- 
manifoldcf/branches/CONNECTORS-781/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/bins/BinManager.java
 (original)
+++ 
manifoldcf/branches/CONNECTORS-781/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/bins/BinManager.java
 Wed Nov 27 11:16:27 2013
@@ -122,6 +122,8 @@ public class BinManager extends org.apac
       IResultRow row = result.getRow(0);
       Double value = (Double)row.getValue(binCounterField);
       double rval = value.doubleValue();
+      if (rval < newBinValue)
+        rval = newBinValue;
       HashMap map = new HashMap();
       map.put(binCounterField,new Double(rval+1.0));
       performUpdate(map," WHERE "+query,params,null);

Modified: 
manifoldcf/branches/CONNECTORS-781/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/interfaces/QueueTracker.java
URL: 
http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-781/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/interfaces/QueueTracker.java?rev=1545996&r1=1545995&r2=1545996&view=diff
==============================================================================
--- 
manifoldcf/branches/CONNECTORS-781/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/interfaces/QueueTracker.java
 (original)
+++ 
manifoldcf/branches/CONNECTORS-781/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/interfaces/QueueTracker.java
 Wed Nov 27 11:16:27 2013
@@ -60,10 +60,6 @@ public class QueueTracker
   /** These are the accumulated performance averages for all connections etc. 
*/
   protected final PerformanceStatistics performanceStatistics = new 
PerformanceStatistics();
 
-  /** These are the bin counts for a prioritization pass.
-  * This hash table is keyed by bin, and contains DoubleBinCount objects as 
values */
-  protected final Map<String,DoubleBinCount> binCounts = new 
HashMap<String,DoubleBinCount>();
-
   /** These are the bin counts for tracking the documents that are on
   * the active queue, but are not being processed yet */
   protected final Map<String,BinCount> queuedBinCounts = new 
HashMap<String,BinCount>();
@@ -71,6 +67,9 @@ public class QueueTracker
   /** These are the bin counts for active threads */
   protected final Map<String,BinCount> activeBinCounts = new 
HashMap<String,BinCount>();
 
+  /** The locker for the minimum depth calculation */
+  protected final Integer minimumDepthLock = new Integer(0);
+  
   /** The "minimum depth" - which is the smallest bin count of the last 
document queued.  This helps guarantee that documents that are
   * newly discovered don't wind up with high priority, but instead wind up 
about the same as the currently active document priority. */
   protected double currentMinimumDepth = 0.0;
@@ -90,9 +89,8 @@ public class QueueTracker
   */
   public void beginReset()
   {
-    synchronized (binCounts)
+    synchronized (minimumDepthLock)
     {
-      binCounts.clear();
       currentMinimumDepth = 0.0;
       resetInProgress = true;
     }
@@ -102,7 +100,7 @@ public class QueueTracker
   /** Finish the reset operation */
   public void endReset()
   {
-    synchronized (binCounts)
+    synchronized (minimumDepthLock)
     {
       resetInProgress = false;
     }
@@ -220,7 +218,7 @@ public class QueueTracker
   */
   public void assessMinimumDepth(Double[] binNamesSet)
   {
-    synchronized (binCounts)
+    synchronized (minimumDepthLock)
     {
       // Ignore all numbers until reset is complete
       if (!resetInProgress)
@@ -343,223 +341,16 @@ public class QueueTracker
     return rval;
   }
 
-  /** This is a made-up constant, originally based on 100 documents/second, 
but adjusted downward as a result of experimentation and testing, which is 
described as "T" below.
-  */
-  private final static double minMsPerFetch = 50.0;
-
-  /** Calculate a document priority value.  Priorities are reversed, and in 
log space, so that
-  * zero (0.0) is considered the highest possible priority, and larger 
priority values are considered lower in actual priority.
-  *@param binNames are the global bins to which the document belongs.
-  *@param connection is the connection, from which the throttles may be 
obtained.  More highly throttled connections are given
-  *          less favorable priority.
-  *@return the priority value, based on recent history.  Also updates 
statistics atomically.
-  */
-  public double calculatePriority(String[] binNames, IRepositoryConnection 
connection)
-  {
-
-    // NOTE: We must be sure to adjust the return value by the factor 
calculated due to performance; a slower throttle rate
-    // should yield a lower priority.  In theory it should be possible to 
calculate an adjusted priority pretty exactly,
-    // on the basis that the fetch rates of two distinct bins should grant 
priorities such that:
-    //
-    //  (n documents) / (the rate of fetch (docs/millisecond) of the first 
bin) = milliseconds for the first bin
-    //
-    //  should equal:
-    //
-    //  (m documents) / (the rate of fetch of the second bin) = milliseconds 
for the second bin
-    //
-    // ... and then assigning priorities so that after a given number of 
document priorities are assigned from the first bin, the
-    // corresponding (*m/n) number of document priorities would get assigned 
for the second bin.
-    //
-    // Suppose the maximum fetch rate for the document is F fetches per 
millisecond.  If the document priority assigned for the Bth
-    // bin member is -log(1/(1+B)) for a document fetched with no throttling 
whatsoever,
-    // then we want the priority to be -log(1/(1+k)) for a throttled bin, 
where k is chosen so that:
-    // k = B * ((T + 1/F)/T) = B * (1 + 1/TF)
-    // ... where T is the time taken to fetch a single document that has no 
throttling at all.
-    // For the purposes of this exercise, a value of 100 doc/sec, or T=10ms.
-    //
-    // Basically, for F = 0, k should be infinity, and for F = infinity, k 
should be B.
-
-    // First, calculate the document's max fetch rate, in fetches per 
millisecond.  This will be used to adjust the priority, and
-    // also when resetting the bin counts.
-    double[] maxFetchRates = calculateMaxFetchRates(binNames,connection);
-
-    // For each bin, we will be calculating the bin count scale factor, which 
is what we multiply the bincount by to adjust for the
-    // throttling on that bin.
-    double[] binCountScaleFactors = new double[binNames.length];
-    double[] weightedMinimumDepths = new double[binNames.length];
-
-    // Before calculating priority, calculate some factors that will allow us 
to determine the proper starting value for a bin.
-
-    // First thing to do is to reset the bin values based on the current 
minimum.
-    for (int i = 0; i < binNames.length; i++)
-    {
-      String binName = binNames[i];
-      // Remember, maxFetchRate is in fetches per ms.
-      double maxFetchRate = maxFetchRates[i];
-
-      // Calculate (and save for later) the scale factor for this bin.
-      double binCountScaleFactor;
-      if (maxFetchRate == 0.0)
-        binCountScaleFactor = Double.POSITIVE_INFINITY;
-      else
-        binCountScaleFactor = 1.0 + 1.0 / (minMsPerFetch * maxFetchRate);
-      binCountScaleFactors[i] = binCountScaleFactor;
-      weightedMinimumDepths[i] = currentMinimumDepth / binCountScaleFactor;
-    }
-
-    double highestAdjustedCount = 0.0;
-    synchronized (binCounts)
-    {
-      // Find the bin with the largest effective count, and use that for the 
document's priority.
-      // (This of course assumes that the slowest throttle is the one that 
wins.)
-      for (int i = 0; i < binNames.length; i++)
-      {
-        String binName = binNames[i];
-        double binCountScaleFactor = binCountScaleFactors[i];
-        double weightedMinimumDepth = weightedMinimumDepths[i];
-
-        double thisCount = 0.0;
-        DoubleBinCount bc = binCounts.get(binName);
-        if (bc != null)
-          thisCount = bc.getValue();
-        else
-        {
-          bc = new DoubleBinCount();
-          binCounts.put(binName,bc);
-        }
-
-        // Adjust the count, if needed, so that we are not assigning 
priorities greater than the current level we are
-        // grabbing documents at
-        if (thisCount < weightedMinimumDepth)
-        {
-
-          if (Logging.scheduling.isDebugEnabled())
-            Logging.scheduling.debug("Resetting value of bin '"+binName+"' to 
"+new Double(weightedMinimumDepth).toString()+"(scale factor is "+new 
Double(binCountScaleFactor)+")");
-
-          // Set a new bin value
-          bc.setValue(weightedMinimumDepth);
-        }
-        bc.increment();
-
-        double adjustedCount;
-        // Use the scale factor already calculated above to yield a priority 
that is adjusted for the fetch rate.
-        if (binCountScaleFactor == Double.POSITIVE_INFINITY)
-          adjustedCount = Double.POSITIVE_INFINITY;
-        else
-          adjustedCount = thisCount * binCountScaleFactor;
-        if (adjustedCount > highestAdjustedCount)
-          highestAdjustedCount = adjustedCount;
-      }
-    }
-    
-    // Calculate the proper log value
-    double returnValue;
-    
-    if (highestAdjustedCount == Double.POSITIVE_INFINITY)
-      returnValue = Double.POSITIVE_INFINITY;
-    else
-      returnValue = Math.log(1.0 + highestAdjustedCount);
-
-    if (Logging.scheduling.isDebugEnabled())
-    {
-      StringBuilder sb = new StringBuilder();
-      int k = 0;
-      while (k < binNames.length)
-      {
-        sb.append(binNames[k++]).append(" ");
-      }
-      Logging.scheduling.debug("Document with bins ["+sb.toString()+"] given 
priority value "+new Double(returnValue).toString());
-    }
-
-
-    return returnValue;
-  }
-
-  /** Calculate the maximum fetch rate for a given set of bins for a given 
connection.
-  * This is used to adjust the final priority of a document.
+  /** Get the minimum depth.
   */
-  protected static double[] calculateMaxFetchRates(String[] binNames, 
IRepositoryConnection connection)
-  {
-    ThrottleLimits tl = new ThrottleLimits(connection);
-    return tl.getMaximumRates(binNames);
-  }
-
-  /** This class represents the throttle limits out of the connection 
specification */
-  protected static class ThrottleLimits
-  {
-    protected List<ThrottleLimitSpec> specs = new 
ArrayList<ThrottleLimitSpec>();
-
-    public ThrottleLimits(IRepositoryConnection connection)
-    {
-      String[] throttles = connection.getThrottles();
-      int i = 0;
-      while (i < throttles.length)
-      {
-        try
-        {
-          specs.add(new 
ThrottleLimitSpec(throttles[i],(double)connection.getThrottleValue(throttles[i])));
-        }
-        catch (PatternSyntaxException e)
-        {
-        }
-        i++;
-      }
-    }
-
-    public double[] getMaximumRates(String[] binNames)
-    {
-      double[] rval = new double[binNames.length];
-      for (int j = 0 ; j < binNames.length ; j++)
-      {
-        String binName = binNames[j];
-        double maxRate = Double.POSITIVE_INFINITY;
-        for (ThrottleLimitSpec spec : specs)
-        {
-          Pattern p = spec.getRegexp();
-          Matcher m = p.matcher(binName);
-          if (m.find())
-          {
-            double rate = spec.getMaxRate();
-            // The direction of this inequality reflects the fact that the 
throttling is conservative when more rules are present.
-            if (rate < maxRate)
-              maxRate = rate;
-          }
-        }
-        rval[j] = maxRate;
-      }
-      return rval;
-    }
-
-  }
-
-  /** This is a class which describes an individual throttle limit, in fetches 
per millisecond. */
-  protected static class ThrottleLimitSpec
+  public double getMinimumDepth()
   {
-    /** Regexp */
-    protected final Pattern regexp;
-    /** The fetch limit for all bins matching that regexp, in fetches per 
millisecond */
-    protected final double maxRate;
-
-    /** Constructor */
-    public ThrottleLimitSpec(String regexp, double maxRate)
-      throws PatternSyntaxException
+    synchronized (minimumDepthLock)
     {
-      this.regexp = Pattern.compile(regexp);
-      this.maxRate = maxRate;
-    }
-
-    /** Get the regexp. */
-    public Pattern getRegexp()
-    {
-      return regexp;
-    }
-
-    /** Get the max count */
-    public double getMaxRate()
-    {
-      return maxRate;
+      return currentMinimumDepth;
     }
   }
+  
 
   /** This is the class which allows a mutable integer count value to be saved 
in the bincount table.
   */
@@ -606,42 +397,5 @@ public class QueueTracker
     }
   }
 
-  /** This is the class which allows a mutable integer count value to be saved 
in the bincount table.
-  */
-  protected static class DoubleBinCount
-  {
-    /** The count */
-    protected double count = 0.0;
-
-    /** Create */
-    public DoubleBinCount()
-    {
-    }
-
-    public DoubleBinCount duplicate()
-    {
-      DoubleBinCount rval = new DoubleBinCount();
-      rval.count = this.count;
-      return rval;
-    }
-
-    /** Increment the counter */
-    public void increment()
-    {
-      count += 1.0;
-    }
-
-    /** Set the value */
-    public void setValue(double count)
-    {
-      this.count = count;
-    }
-
-    /** Get the value */
-    public double getValue()
-    {
-      return count;
-    }
-  }
 
 }

Modified: 
manifoldcf/branches/CONNECTORS-781/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/ManifoldCF.java
URL: 
http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-781/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/ManifoldCF.java?rev=1545996&r1=1545995&r2=1545996&view=diff
==============================================================================
--- 
manifoldcf/branches/CONNECTORS-781/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/ManifoldCF.java
 (original)
+++ 
manifoldcf/branches/CONNECTORS-781/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/ManifoldCF.java
 Wed Nov 27 11:16:27 2013
@@ -932,6 +932,9 @@ public class ManifoldCF extends org.apac
       // will therefore block that from occurring, until the reset is complete.
       try
       {
+        // Does this need to be in a transaction??? Can it fail and require 
retries?
+        binManager.reset();
+
         // Reprioritize all documents in the jobqueue, 1000 at a time
 
         Map<String,IRepositoryConnection> connectionMap = new 
HashMap<String,IRepositoryConnection>();

Modified: 
manifoldcf/branches/CONNECTORS-781/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/PriorityCalculator.java
URL: 
http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-781/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/PriorityCalculator.java?rev=1545996&r1=1545995&r2=1545996&view=diff
==============================================================================
--- 
manifoldcf/branches/CONNECTORS-781/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/PriorityCalculator.java
 (original)
+++ 
manifoldcf/branches/CONNECTORS-781/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/PriorityCalculator.java
 Wed Nov 27 11:16:27 2013
@@ -21,6 +21,8 @@ package org.apache.manifoldcf.crawler.sy
 import org.apache.manifoldcf.core.interfaces.*;
 import org.apache.manifoldcf.agents.interfaces.*;
 import org.apache.manifoldcf.crawler.interfaces.*;
+import java.util.*;
+import java.util.regex.*;
 
 /** This class calculates a document priority given all the required inputs.
 * It is not thread safe, but calls classes that are (e.g. QueueTracker).
@@ -29,9 +31,13 @@ public class PriorityCalculator implemen
 {
   public static final String _rcsid = "@(#)$Id$";
 
+  /** This is a made-up constant, originally based on 100 documents/second, 
but adjusted downward as a result of experimentation and testing, which is 
described as "T" below.
+  */
+  private final static double minMsPerFetch = 50.0;
+
   protected final QueueTracker queueTracker;
   protected final IRepositoryConnection connection;
-  protected final String[] documentBins;
+  protected final String[] binNames;
   protected final IBinManager binManager;
   
   /** Constructor. */
@@ -39,19 +45,201 @@ public class PriorityCalculator implemen
   {
     this.queueTracker = queueTracker;
     this.connection = connection;
-    this.documentBins = documentBins;
+    this.binNames = documentBins;
     this.binManager = binManager;
   }
 
-  /** Compute the document priority given an actual bincounter value.
-  *@return the document priority.
+  /** Calculate a document priority value.  Priorities are reversed, and in 
log space, so that
+  * zero (0.0) is considered the highest possible priority, and larger 
priority values are considered lower in actual priority.
+  *@param binNames are the global bins to which the document belongs.
+  *@param connection is the connection, from which the throttles may be 
obtained.  More highly throttled connections are given
+  *          less favorable priority.
+  *@return the priority value, based on recent history.  Also updates 
statistics atomically.
   */
   @Override
   public double getDocumentPriority()
     throws ManifoldCFException
   {
-    // MHL to use database bin tables
-    return queueTracker.calculatePriority(documentBins,connection);
+
+    // NOTE: We must be sure to adjust the return value by the factor 
calculated due to performance; a slower throttle rate
+    // should yield a lower priority.  In theory it should be possible to 
calculate an adjusted priority pretty exactly,
+    // on the basis that the fetch rates of two distinct bins should grant 
priorities such that:
+    //
+    //  (n documents) / (the rate of fetch (docs/millisecond) of the first 
bin) = milliseconds for the first bin
+    //
+    //  should equal:
+    //
+    //  (m documents) / (the rate of fetch of the second bin) = milliseconds 
for the second bin
+    //
+    // ... and then assigning priorities so that after a given number of 
document priorities are assigned from the first bin, the
+    // corresponding (*m/n) number of document priorities would get assigned 
for the second bin.
+    //
+    // Suppose the maximum fetch rate for the document is F fetches per 
millisecond.  If the document priority assigned for the Bth
+    // bin member is -log(1/(1+B)) for a document fetched with no throttling 
whatsoever,
+    // then we want the priority to be -log(1/(1+k)) for a throttled bin, 
where k is chosen so that:
+    // k = B * ((T + 1/F)/T) = B * (1 + 1/TF)
+    // ... where T is the time taken to fetch a single document that has no 
throttling at all.
+    // For the purposes of this exercise, a value of 100 doc/sec, or T=10ms.
+    //
+    // Basically, for F = 0, k should be infinity, and for F = infinity, k 
should be B.
+
+    // First, calculate the document's max fetch rate, in fetches per 
millisecond.  This will be used to adjust the priority, and
+    // also when resetting the bin counts.
+    double[] maxFetchRates = calculateMaxFetchRates(binNames,connection);
+
+    // For each bin, we will be calculating the bin count scale factor, which 
is what we multiply the bincount by to adjust for the
+    // throttling on that bin.
+    double[] binCountScaleFactors = new double[binNames.length];
+    double[] weightedMinimumDepths = new double[binNames.length];
+
+    // Before calculating priority, calculate some factors that will allow us 
to determine the proper starting value for a bin.
+    double currentMinimumDepth = queueTracker.getMinimumDepth();
+
+    // First thing to do is to reset the bin values based on the current 
minimum.
+    for (int i = 0; i < binNames.length; i++)
+    {
+      String binName = binNames[i];
+      // Remember, maxFetchRate is in fetches per ms.
+      double maxFetchRate = maxFetchRates[i];
+
+      // Calculate (and save for later) the scale factor for this bin.
+      double binCountScaleFactor;
+      if (maxFetchRate == 0.0)
+        binCountScaleFactor = Double.POSITIVE_INFINITY;
+      else
+        binCountScaleFactor = 1.0 + 1.0 / (minMsPerFetch * maxFetchRate);
+      binCountScaleFactors[i] = binCountScaleFactor;
+      weightedMinimumDepths[i] = currentMinimumDepth / binCountScaleFactor;
+    }
+
+    double highestAdjustedCount = 0.0;
+    // Find the bin with the largest effective count, and use that for the 
document's priority.
+    // (This of course assumes that the slowest throttle is the one that wins.)
+    for (int i = 0; i < binNames.length; i++)
+    {
+      String binName = binNames[i];
+      double binCountScaleFactor = binCountScaleFactors[i];
+      double weightedMinimumDepth = weightedMinimumDepths[i];
+
+      double thisCount = 
binManager.getIncrementBinValue(binName,weightedMinimumDepth);
+      double adjustedCount;
+      // Use the scale factor already calculated above to yield a priority 
that is adjusted for the fetch rate.
+      if (binCountScaleFactor == Double.POSITIVE_INFINITY)
+        adjustedCount = Double.POSITIVE_INFINITY;
+      else
+        adjustedCount = thisCount * binCountScaleFactor;
+      if (adjustedCount > highestAdjustedCount)
+        highestAdjustedCount = adjustedCount;
+    }
+    
+    // Calculate the proper log value
+    double returnValue;
+    
+    if (highestAdjustedCount == Double.POSITIVE_INFINITY)
+      returnValue = Double.POSITIVE_INFINITY;
+    else
+      returnValue = Math.log(1.0 + highestAdjustedCount);
+
+    if (Logging.scheduling.isDebugEnabled())
+    {
+      StringBuilder sb = new StringBuilder();
+      int k = 0;
+      while (k < binNames.length)
+      {
+        sb.append(binNames[k++]).append(" ");
+      }
+      Logging.scheduling.debug("Document with bins ["+sb.toString()+"] given 
priority value "+new Double(returnValue).toString());
+    }
+
+
+    return returnValue;
+  }
+
+
+  /** Calculate the maximum fetch rate for a given set of bins for a given 
connection.
+  * This is used to adjust the final priority of a document.
+  */
+  protected static double[] calculateMaxFetchRates(String[] binNames, 
IRepositoryConnection connection)
+  {
+    ThrottleLimits tl = new ThrottleLimits(connection);
+    return tl.getMaximumRates(binNames);
+  }
+
+  /** This class represents the throttle limits out of the connection 
specification */
+  protected static class ThrottleLimits
+  {
+    protected List<ThrottleLimitSpec> specs = new 
ArrayList<ThrottleLimitSpec>();
+
+    public ThrottleLimits(IRepositoryConnection connection)
+    {
+      String[] throttles = connection.getThrottles();
+      int i = 0;
+      while (i < throttles.length)
+      {
+        try
+        {
+          specs.add(new 
ThrottleLimitSpec(throttles[i],(double)connection.getThrottleValue(throttles[i])));
+        }
+        catch (PatternSyntaxException e)
+        {
+        }
+        i++;
+      }
+    }
+
+    public double[] getMaximumRates(String[] binNames)
+    {
+      double[] rval = new double[binNames.length];
+      for (int j = 0 ; j < binNames.length ; j++)
+      {
+        String binName = binNames[j];
+        double maxRate = Double.POSITIVE_INFINITY;
+        for (ThrottleLimitSpec spec : specs)
+        {
+          Pattern p = spec.getRegexp();
+          Matcher m = p.matcher(binName);
+          if (m.find())
+          {
+            double rate = spec.getMaxRate();
+            // The direction of this inequality reflects the fact that the 
throttling is conservative when more rules are present.
+            if (rate < maxRate)
+              maxRate = rate;
+          }
+        }
+        rval[j] = maxRate;
+      }
+      return rval;
+    }
+
+  }
+
+  /** This is a class which describes an individual throttle limit, in fetches 
per millisecond. */
+  protected static class ThrottleLimitSpec
+  {
+    /** Regexp */
+    protected final Pattern regexp;
+    /** The fetch limit for all bins matching that regexp, in fetches per 
millisecond */
+    protected final double maxRate;
+
+    /** Constructor */
+    public ThrottleLimitSpec(String regexp, double maxRate)
+      throws PatternSyntaxException
+    {
+      this.regexp = Pattern.compile(regexp);
+      this.maxRate = maxRate;
+    }
+
+    /** Get the regexp. */
+    public Pattern getRegexp()
+    {
+      return regexp;
+    }
+
+    /** Get the max count */
+    public double getMaxRate()
+    {
+      return maxRate;
+    }
   }
 
 }


Reply via email to