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.transfer;
21  
22  import java.util.ArrayList;
23  import java.util.*;
24  import java.util.Comparator;
25  import java.util.HashSet;
26  import java.util.Set;
27  
28  import org.xnap.util.*;
29  
30  /***
31   * This class manages transfers in a queue and notifies transfers when they
32   * are scheduled to start.
33   */
34  public class TransferQueue {
35  
36      //--- Constant(s) ---
37  
38  	public static int RESORT_INTERVAL = 20 * 1000;
39  
40      //--- Data field(s) ---
41  
42      private ArrayList queue = new ArrayList();
43      private Set running = new HashSet();
44      private int maxSlots;
45      
46      //--- Constructor(s) ---
47  
48      public TransferQueue(int maxSlots)
49      {
50  		this.maxSlots = maxSlots;
51  
52  		Scheduler.run(RESORT_INTERVAL, RESORT_INTERVAL, new ResortTask());
53      }
54  
55      public TransferQueue()
56      {
57  		this(0);
58      }
59  
60      //--- Method(s) ---
61  
62      /***
63       * Adds <code>item</code> to the queue.
64       *
65       * @return the queue position
66       */
67      public synchronized int add(Queueable item)
68      {
69  		queue.add(item);
70  		resort();
71  		return item.getQueuePosition();
72      }
73  
74  	public double calculatePriority(Queueable item)
75  	{
76  		double value = System.currentTimeMillis() - item.getEnqueueTime();
77  		long size = item.getFilesize() / 1024;
78  		if (size > 0) {
79  			value /= size;
80  		}
81  		return value * item.getPriority();
82  	}
83  
84      /***
85       * Removes <code>item</code> from the queue and updates the position
86       * of all tail items.
87  	 *
88  	 * @return true, if item was removed; false, if item was not in queue
89       */
90      public synchronized boolean remove(Queueable item)
91      {
92  		if (running.remove(item) || queue.remove(item)) {
93  			resort();
94  			return true;
95  		}
96  		return false;
97      }
98  
99      /***
100      * Returns the number of free slots.
101      */
102     public synchronized int getFreeSlots()
103     {
104 		return maxSlots - running.size();
105     }
106 
107     /***
108      * Sets the number of slots to <code>maxSlots</code>.
109      */
110     public synchronized void setMaxSlots(int maxSlots)
111     {
112 		this.maxSlots = maxSlots;
113 		update();
114     }
115 
116 	public synchronized void resort()
117 	{
118 		// FIX: sort may possibly fail, because pritorities can change
119 		// dynamically during sort
120 		Collections.sort(queue, new QueueableComparator());
121 		update();
122 	}
123 
124     /***
125      * Checks the queue if any items can be started.
126      */
127     private synchronized void update()
128     {
129 		int i = 1;
130 		for (Iterator it = queue.iterator(); it.hasNext();) {
131 			Queueable item = (Queueable)it.next();
132 			if (getFreeSlots() > 0) {
133 				if (item.startTransfer()) {
134 					item.setQueuePosition(0);
135 					running.add(item);
136 					it.remove();
137 					continue;
138 				}
139 			}
140 
141 			item.setQueuePosition(i);
142 			i++;
143 		}
144     }
145 
146     /***
147      * Compars Queueable objects. Sorts higher priorities first.
148      */
149 	private class QueueableComparator implements Comparator
150 	{
151 	
152 		public int compare(Object o1, Object o2) 
153 		{
154 			double p1 = calculatePriority((Queueable)o1);
155 			double p2 = calculatePriority((Queueable)o2);
156 
157 		    return (p1 < p2) ? 1 : (p1 == p2) ? 0 : -1;
158 		}
159 			
160 	}
161 
162     /***
163      * Resorts the queue in regular intervals
164      */
165 	private class ResortTask extends XNapTask {
166 
167 		public ResortTask() 
168 		{
169 		}
170 
171 		public void run() 
172 		{
173 			if (getFreeSlots() > 0) {
174 				resort();
175 			}
176 		}
177 
178     }
179 
180 }