View Javadoc

1   /*
2    *  XNap - A P2P framework and client.
3    *
4    *  See the file AUTHORS for copyright information.
5    *
6    *  This program is free software; you can redistribute it and/or modify
7    *  it under the terms of the GNU General Public License as published by
8    *  the Free Software Foundation.
9    *
10   *  This program is distributed in the hope that it will be useful,
11   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   *  GNU General Public License for more details.
14   *
15   *  You should have received a copy of the GNU General Public License
16   *  along with this program; if not, write to the Free Software
17   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   */
19  
20  package org.xnap.io;
21  
22  import java.util.Iterator;
23  import java.util.LinkedList;
24  
25  import org.xnap.util.Scheduler;
26  
27  /***
28   * 
29   */
30  public class BandwidthManager {
31  
32      //--- Constant(s) ---
33  
34      /***
35       * The default length of a tick.
36       */
37      public static final long TICK_LENGTH = 250;
38  
39      // --- Data Field(s) ---
40  
41  	private LinkedList listeners;
42      private long bandwidth;
43      private long totalBandwidth;
44  	private int consumers;
45  	private int externalConsumers;
46  	private LinkedList queue = new LinkedList();
47  	private int totalWeight;
48  
49      // --- Constructor(s) ---
50  
51      public BandwidthManager() 
52      {
53  		Scheduler.run(0, TICK_LENGTH, new TickRunner());
54      }
55  	
56      // --- Method(s) ---
57  
58  	public synchronized void addBandwidthListener()
59  	{
60  	}
61  
62  	/***
63  	 * Returns true, if bandwidth was allocated.
64  	 */
65  	public synchronized boolean allocate(BandwidthManagable transfer)
66  		throws InterruptedException
67  	{
68  		if (bandwidth > 0) {
69  			totalWeight += transfer.getPriority() + 1;
70  			queue.add(transfer);
71  			this.wait();
72  			return true;
73  		}
74  		else {
75  			return false;
76  		}
77  	}
78  
79  	public synchronized void consume(int weight, boolean external)
80  	{
81  		if (external) {
82  			externalConsumers += weight;
83  		}
84  		else {
85  			consumers += weight;
86  		}
87  		updateBandwidth();
88  	}
89  
90      public synchronized void setBandwidth(long newValue)
91      {
92  		totalBandwidth = newValue;
93  		updateBandwidth();
94      }
95  
96  	private void updateBandwidth()
97  	{
98  		int total = externalConsumers + consumers;
99  		//long slice = (total > 0) ? totalBandwidth / total : 0;
100 		bandwidth = (total > 0) 
101 			? (totalBandwidth * consumers) / total
102 			: 0;
103 		bandwidth = (bandwidth * TICK_LENGTH) / 1000;
104 	}
105 
106 	//--- Inner Class(es) ---
107 
108 	public class TickRunner implements Runnable
109 	{
110 		public void run()
111 		{
112 			synchronized (BandwidthManager.this) {
113 				if (totalWeight > 0) {
114 					long bandwidthPerTransfer = bandwidth / totalWeight;
115 					for (Iterator i = queue.iterator(); i.hasNext();) {
116 						BandwidthManagable transfer
117 							= (BandwidthManagable)i.next();
118 						transfer.setAllocated(bandwidthPerTransfer
119 											  * (transfer.getPriority() + 1));
120 					}
121 
122 					totalWeight = 0;
123 					queue.clear();
124 
125 					BandwidthManager.this.notifyAll();
126 				}
127 			}
128 		}
129 	}
130 	
131 }