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 }