1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.xnap.io;
21
22
23 /***
24 * Provides a throttle implementation based on time ticks. Clients can
25 * allocate a limited amount of bytes for each tick. If all bandwidth
26 * has been allocated clients are stalled until the next tick.
27 */
28 public class ThrottleSupport
29 {
30
31
32
33 /***
34 * The default length of a tick.
35 */
36 public static final long TICK_LENGTH = 250;
37
38
39
40
41
42 /***
43 * bytes per tick
44 */
45 protected long bandwidth = 0;
46 protected long allocated = 0;
47 protected long tickStart = 0;
48 protected Object lock = new Object();
49
50
51
52 public ThrottleSupport()
53 {
54 }
55
56
57
58 /***
59 * Returns the preferred block size each client should try to
60 * allocate at a time. This makes sure each client gets a fair
61 * share of the bandwidth.
62 *
63 * @see #allocate(int)
64 */
65 public int getPreferredBlocksize()
66 {
67 synchronized (lock) {
68 long bs = bandwidth / 4;
69 return bs == 0 ? 512 : bs < 64 ? 64 : bs > 512 ? 512 : (int)bs;
70 }
71 }
72
73 /***
74 * Sets the maximum bandwidth.
75 *
76 * @param bandwidth byte / s
77 */
78 public void setBandwidth(long bandwidth)
79 {
80 synchronized (lock) {
81 this.bandwidth = (bandwidth * TICK_LENGTH) / 1000;
82 }
83 }
84
85 /***
86 * Returns the number of bytes that the calling thread is allowed to
87 * send. Blocks until at least one byte could be allocated.
88 *
89 * @return -1, if interrupted;
90 */
91 public int allocate(int bytes)
92 {
93 synchronized (lock) {
94 while (true) {
95 if (System.currentTimeMillis() - tickStart >= TICK_LENGTH) {
96
97 tickStart = System.currentTimeMillis();
98 allocated = 0;
99
100 }
101
102 if (bandwidth == 0) {
103
104 return bytes;
105 }
106 else if (bytes < bandwidth - allocated) {
107
108 allocated += bytes;
109
110 return bytes;
111 }
112 else if (bandwidth - allocated > 0) {
113
114 bytes = (int)(bandwidth - allocated);
115 allocated = bandwidth;
116
117 return bytes;
118 }
119
120
121
122
123
124 long t
125 = (TICK_LENGTH - (System.currentTimeMillis() - tickStart));
126 if (t > 0) {
127 try {
128
129 lock.wait(t);
130 }
131 catch (InterruptedException e) {
132 return -1;
133 }
134 }
135 }
136 }
137 }
138
139 }