1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.http.pool;
28
29 import java.util.HashSet;
30 import java.util.Iterator;
31 import java.util.LinkedList;
32 import java.util.Set;
33 import java.util.concurrent.Future;
34
35 import org.apache.http.util.Args;
36 import org.apache.http.util.Asserts;
37
38 abstract class RouteSpecificPool<T, C, E extends PoolEntry<T, C>> {
39
40 private final T route;
41 private final Set<E> leased;
42 private final LinkedList<E> available;
43 private final LinkedList<Future<E>> pending;
44
45 RouteSpecificPool(final T route) {
46 super();
47 this.route = route;
48 this.leased = new HashSet<E>();
49 this.available = new LinkedList<E>();
50 this.pending = new LinkedList<Future<E>>();
51 }
52
53 protected abstract E createEntry(C conn);
54
55 public final T getRoute() {
56 return route;
57 }
58
59 public int getLeasedCount() {
60 return this.leased.size();
61 }
62
63 public int getPendingCount() {
64 return this.pending.size();
65 }
66
67 public int getAvailableCount() {
68 return this.available.size();
69 }
70
71 public int getAllocatedCount() {
72 return this.available.size() + this.leased.size();
73 }
74
75 public E getFree(final Object state) {
76 if (!this.available.isEmpty()) {
77 if (state != null) {
78 final Iterator<E> it = this.available.iterator();
79 while (it.hasNext()) {
80 final E entry = it.next();
81 if (state.equals(entry.getState())) {
82 it.remove();
83 this.leased.add(entry);
84 return entry;
85 }
86 }
87 }
88 final Iterator<E> it = this.available.iterator();
89 while (it.hasNext()) {
90 final E entry = it.next();
91 if (entry.getState() == null) {
92 it.remove();
93 this.leased.add(entry);
94 return entry;
95 }
96 }
97 }
98 return null;
99 }
100
101 public E getLastUsed() {
102 return this.available.isEmpty() ? null : this.available.getLast();
103 }
104
105 public boolean remove(final E entry) {
106 Args.notNull(entry, "Pool entry");
107 if (!this.available.remove(entry)) {
108 if (!this.leased.remove(entry)) {
109 return false;
110 }
111 }
112 return true;
113 }
114
115 public void free(final E entry, final boolean reusable) {
116 Args.notNull(entry, "Pool entry");
117 final boolean found = this.leased.remove(entry);
118 Asserts.check(found, "Entry %s has not been leased from this pool", entry);
119 if (reusable) {
120 this.available.addFirst(entry);
121 }
122 }
123
124 public E add(final C conn) {
125 final E entry = createEntry(conn);
126 this.leased.add(entry);
127 return entry;
128 }
129
130 public void queue(final Future<E> future) {
131 if (future == null) {
132 return;
133 }
134 this.pending.add(future);
135 }
136
137 public Future<E> nextPending() {
138 return this.pending.poll();
139 }
140
141 public void unqueue(final Future<E> future) {
142 if (future == null) {
143 return;
144 }
145
146 this.pending.remove(future);
147 }
148
149 public void shutdown() {
150 for (final Future<E> future: this.pending) {
151 future.cancel(true);
152 }
153 this.pending.clear();
154 for (final E entry: this.available) {
155 entry.close();
156 }
157 this.available.clear();
158 for (final E entry: this.leased) {
159 entry.close();
160 }
161 this.leased.clear();
162 }
163
164 @Override
165 public String toString() {
166 final StringBuilder buffer = new StringBuilder();
167 buffer.append("[route: ");
168 buffer.append(this.route);
169 buffer.append("][leased: ");
170 buffer.append(this.leased.size());
171 buffer.append("][available: ");
172 buffer.append(this.available.size());
173 buffer.append("][pending: ");
174 buffer.append(this.pending.size());
175 buffer.append("]");
176 return buffer.toString();
177 }
178
179 }