1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
37
38 public static int RESORT_INTERVAL = 20 * 1000;
39
40
41
42 private ArrayList queue = new ArrayList();
43 private Set running = new HashSet();
44 private int maxSlots;
45
46
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
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
119
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 }