View Javadoc

1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
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  
34  import org.apache.http.annotation.NotThreadSafe;
35  import org.apache.http.util.Args;
36  import org.apache.http.util.Asserts;
37  
38  @NotThreadSafe
39  abstract class RouteSpecificPool<T, C, E extends PoolEntry<T, C>> {
40  
41      private final T route;
42      private final Set<E> leased;
43      private final LinkedList<E> available;
44      private final LinkedList<PoolEntryFuture<E>> pending;
45  
46      RouteSpecificPool(final T route) {
47          super();
48          this.route = route;
49          this.leased = new HashSet<E>();
50          this.available = new LinkedList<E>();
51          this.pending = new LinkedList<PoolEntryFuture<E>>();
52      }
53  
54      protected abstract E createEntry(C conn);
55  
56      public final T getRoute() {
57          return route;
58      }
59  
60      public int getLeasedCount() {
61          return this.leased.size();
62      }
63  
64      public int getPendingCount() {
65          return this.pending.size();
66      }
67  
68      public int getAvailableCount() {
69          return this.available.size();
70      }
71  
72      public int getAllocatedCount() {
73          return this.available.size() + this.leased.size();
74      }
75  
76      public E getFree(final Object state) {
77          if (!this.available.isEmpty()) {
78              if (state != null) {
79                  final Iterator<E> it = this.available.iterator();
80                  while (it.hasNext()) {
81                      final E entry = it.next();
82                      if (state.equals(entry.getState())) {
83                          it.remove();
84                          this.leased.add(entry);
85                          return entry;
86                      }
87                  }
88              }
89              final Iterator<E> it = this.available.iterator();
90              while (it.hasNext()) {
91                  final E entry = it.next();
92                  if (entry.getState() == null) {
93                      it.remove();
94                      this.leased.add(entry);
95                      return entry;
96                  }
97              }
98          }
99          return null;
100     }
101 
102     public E getLastUsed() {
103         if (!this.available.isEmpty()) {
104             return this.available.getLast();
105         } else {
106             return null;
107         }
108     }
109 
110     public boolean remove(final E entry) {
111         Args.notNull(entry, "Pool entry");
112         if (!this.available.remove(entry)) {
113             if (!this.leased.remove(entry)) {
114                 return false;
115             }
116         }
117         return true;
118     }
119 
120     public void free(final E entry, final boolean reusable) {
121         Args.notNull(entry, "Pool entry");
122         final boolean found = this.leased.remove(entry);
123         Asserts.check(found, "Entry %s has not been leased from this pool", entry);
124         if (reusable) {
125             this.available.addFirst(entry);
126         }
127     }
128 
129     public E add(final C conn) {
130         final E entry = createEntry(conn);
131         this.leased.add(entry);
132         return entry;
133     }
134 
135     public void queue(final PoolEntryFuture<E> future) {
136         if (future == null) {
137             return;
138         }
139         this.pending.add(future);
140     }
141 
142     public PoolEntryFuture<E> nextPending() {
143         return this.pending.poll();
144     }
145 
146     public void unqueue(final PoolEntryFuture<E> future) {
147         if (future == null) {
148             return;
149         }
150 
151         this.pending.remove(future);
152     }
153 
154     public void shutdown() {
155         for (final PoolEntryFuture<E> future: this.pending) {
156             future.cancel(true);
157         }
158         this.pending.clear();
159         for (final E entry: this.available) {
160             entry.close();
161         }
162         this.available.clear();
163         for (final E entry: this.leased) {
164             entry.close();
165         }
166         this.leased.clear();
167     }
168 
169     @Override
170     public String toString() {
171         final StringBuilder buffer = new StringBuilder();
172         buffer.append("[route: ");
173         buffer.append(this.route);
174         buffer.append("][leased: ");
175         buffer.append(this.leased.size());
176         buffer.append("][available: ");
177         buffer.append(this.available.size());
178         buffer.append("][pending: ");
179         buffer.append(this.pending.size());
180         buffer.append("]");
181         return buffer.toString();
182     }
183 
184 }