001 /*
002 @license.text@
003 */
004 package biz.hammurapi.util;
005
006 import java.util.ArrayList;
007 import java.util.Collections;
008 import java.util.Iterator;
009 import java.util.List;
010
011 /**
012 * Load balancer distributes work to other workers
013 * according to weights. The less the weight the more
014 * job worker is getting.
015 * @author Pavel Vlasov
016 * @revision $Revision$
017 */
018 public class LoadBalancer implements Worker {
019
020 private List workers=new ArrayList();
021
022 private void descore() {
023 synchronized (workers) {
024 Iterator it=workers.iterator();
025 while (it.hasNext()) {
026 ((WorkerEntry) it.next()).score-=Integer.MAX_VALUE;
027 }
028 }
029 }
030
031 private class WorkerEntry implements Comparable {
032 Worker worker;
033 int weight;
034 int score;
035
036 /**
037 * @param worker
038 * @param weight Must be >0
039 */
040 WorkerEntry(Worker worker, int weight) {
041 super();
042 if (weight<1) {
043 throw new IllegalArgumentException("Worker weight must be >0");
044 }
045 this.worker = worker;
046 this.weight = weight;
047 }
048
049 public int compareTo(Object o) {
050 if (o instanceof WorkerEntry) {
051 return score-((WorkerEntry) o).score;
052 }
053
054 return hashCode()-o.hashCode();
055 }
056
057 boolean post(Runnable job) {
058 if (worker.post(job)) {
059 // reduce all scores to avoid overflow.
060 if (score>Integer.MAX_VALUE-weight) {
061 descore();
062 }
063
064 score+=weight;
065 return true;
066 }
067 return false;
068 }
069 }
070
071 public boolean post(Runnable job) {
072 synchronized (workers) {
073 Collections.sort(workers);
074 Iterator it=workers.iterator();
075 while (it.hasNext()) {
076 WorkerEntry we=(WorkerEntry) it.next();
077 if (we.post(job)) {
078 return true;
079 }
080 }
081 }
082
083 return false;
084 }
085
086 public void addWorker(Worker worker, int weight) {
087 synchronized (workers) {
088 workers.add(new WorkerEntry(worker, weight));
089 }
090 }
091 }