|
@@ -22,6 +22,7 @@ import java.io.IOException;
|
|
import java.lang.reflect.Constructor;
|
|
import java.lang.reflect.Constructor;
|
|
import java.lang.reflect.InvocationTargetException;
|
|
import java.lang.reflect.InvocationTargetException;
|
|
import java.util.AbstractQueue;
|
|
import java.util.AbstractQueue;
|
|
|
|
+import java.util.Arrays;
|
|
import java.util.Collection;
|
|
import java.util.Collection;
|
|
import java.util.Iterator;
|
|
import java.util.Iterator;
|
|
import java.util.concurrent.BlockingQueue;
|
|
import java.util.concurrent.BlockingQueue;
|
|
@@ -77,8 +78,10 @@ public class CallQueueManager<E extends Schedulable>
|
|
int priorityLevels = parseNumLevels(namespace, conf);
|
|
int priorityLevels = parseNumLevels(namespace, conf);
|
|
this.scheduler = createScheduler(schedulerClass, priorityLevels,
|
|
this.scheduler = createScheduler(schedulerClass, priorityLevels,
|
|
namespace, conf);
|
|
namespace, conf);
|
|
|
|
+ int[] capacityWeights = parseCapacityWeights(priorityLevels,
|
|
|
|
+ namespace, conf);
|
|
BlockingQueue<E> bq = createCallQueueInstance(backingClass,
|
|
BlockingQueue<E> bq = createCallQueueInstance(backingClass,
|
|
- priorityLevels, maxQueueSize, namespace, conf);
|
|
|
|
|
|
+ priorityLevels, maxQueueSize, namespace, capacityWeights, conf);
|
|
this.clientBackOffEnabled = clientBackOffEnabled;
|
|
this.clientBackOffEnabled = clientBackOffEnabled;
|
|
this.serverFailOverEnabled = conf.getBoolean(
|
|
this.serverFailOverEnabled = conf.getBoolean(
|
|
namespace + "." +
|
|
namespace + "." +
|
|
@@ -146,13 +149,14 @@ public class CallQueueManager<E extends Schedulable>
|
|
|
|
|
|
private <T extends BlockingQueue<E>> T createCallQueueInstance(
|
|
private <T extends BlockingQueue<E>> T createCallQueueInstance(
|
|
Class<T> theClass, int priorityLevels, int maxLen, String ns,
|
|
Class<T> theClass, int priorityLevels, int maxLen, String ns,
|
|
- Configuration conf) {
|
|
|
|
|
|
+ int[] capacityWeights, Configuration conf) {
|
|
|
|
|
|
// Used for custom, configurable callqueues
|
|
// Used for custom, configurable callqueues
|
|
try {
|
|
try {
|
|
Constructor<T> ctor = theClass.getDeclaredConstructor(int.class,
|
|
Constructor<T> ctor = theClass.getDeclaredConstructor(int.class,
|
|
- int.class, String.class, Configuration.class);
|
|
|
|
- return ctor.newInstance(priorityLevels, maxLen, ns, conf);
|
|
|
|
|
|
+ int.class, String.class, int[].class, Configuration.class);
|
|
|
|
+ return ctor.newInstance(priorityLevels, maxLen, ns,
|
|
|
|
+ capacityWeights, conf);
|
|
} catch (RuntimeException e) {
|
|
} catch (RuntimeException e) {
|
|
throw e;
|
|
throw e;
|
|
} catch (InvocationTargetException e) {
|
|
} catch (InvocationTargetException e) {
|
|
@@ -343,6 +347,47 @@ public class CallQueueManager<E extends Schedulable>
|
|
return retval;
|
|
return retval;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Read the weights of capacity in callqueue and pass the value to
|
|
|
|
+ * callqueue constructions.
|
|
|
|
+ */
|
|
|
|
+ private static int[] parseCapacityWeights(
|
|
|
|
+ int priorityLevels, String ns, Configuration conf) {
|
|
|
|
+ int[] weights = conf.getInts(ns + "." +
|
|
|
|
+ CommonConfigurationKeys.IPC_CALLQUEUE_CAPACITY_WEIGHTS_KEY);
|
|
|
|
+ if (weights.length == 0) {
|
|
|
|
+ weights = getDefaultQueueCapacityWeights(priorityLevels);
|
|
|
|
+ } else if (weights.length != priorityLevels) {
|
|
|
|
+ throw new IllegalArgumentException(
|
|
|
|
+ CommonConfigurationKeys.IPC_CALLQUEUE_CAPACITY_WEIGHTS_KEY + " must "
|
|
|
|
+ + "specify " + priorityLevels + " capacity weights: one for each "
|
|
|
|
+ + "priority level");
|
|
|
|
+ } else {
|
|
|
|
+ // only allow positive numbers
|
|
|
|
+ for (int w : weights) {
|
|
|
|
+ if (w <= 0) {
|
|
|
|
+ throw new IllegalArgumentException(
|
|
|
|
+ CommonConfigurationKeys.IPC_CALLQUEUE_CAPACITY_WEIGHTS_KEY +
|
|
|
|
+ " only takes positive weights. " + w + " capacity weight " +
|
|
|
|
+ "found");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return weights;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * By default, queue capacity is the same for all priority levels.
|
|
|
|
+ *
|
|
|
|
+ * @param priorityLevels number of levels
|
|
|
|
+ * @return default weights
|
|
|
|
+ */
|
|
|
|
+ public static int[] getDefaultQueueCapacityWeights(int priorityLevels) {
|
|
|
|
+ int[] weights = new int[priorityLevels];
|
|
|
|
+ Arrays.fill(weights, 1);
|
|
|
|
+ return weights;
|
|
|
|
+ }
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Replaces active queue with the newly requested one and transfers
|
|
* Replaces active queue with the newly requested one and transfers
|
|
* all calls to the newQ before returning.
|
|
* all calls to the newQ before returning.
|
|
@@ -355,8 +400,9 @@ public class CallQueueManager<E extends Schedulable>
|
|
this.scheduler.stop();
|
|
this.scheduler.stop();
|
|
RpcScheduler newScheduler = createScheduler(schedulerClass, priorityLevels,
|
|
RpcScheduler newScheduler = createScheduler(schedulerClass, priorityLevels,
|
|
ns, conf);
|
|
ns, conf);
|
|
|
|
+ int[] capacityWeights = parseCapacityWeights(priorityLevels, ns, conf);
|
|
BlockingQueue<E> newQ = createCallQueueInstance(queueClassToUse,
|
|
BlockingQueue<E> newQ = createCallQueueInstance(queueClassToUse,
|
|
- priorityLevels, maxSize, ns, conf);
|
|
|
|
|
|
+ priorityLevels, maxSize, ns, capacityWeights, conf);
|
|
|
|
|
|
// Our current queue becomes the old queue
|
|
// Our current queue becomes the old queue
|
|
BlockingQueue<E> oldQ = putRef.get();
|
|
BlockingQueue<E> oldQ = putRef.get();
|