Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
SelectorFactory |
|
| 0.0;0 |
1 | /* | |
2 | * | |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. | |
4 | * | |
5 | * Copyright 2007-2008 Sun Microsystems, Inc. All rights reserved. | |
6 | * | |
7 | * The contents of this file are subject to the terms of either the GNU | |
8 | * General Public License Version 2 only ("GPL") or the Common Development | |
9 | * and Distribution License("CDDL") (collectively, the "License"). You | |
10 | * may not use this file except in compliance with the License. You can obtain | |
11 | * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html | |
12 | * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific | |
13 | * language governing permissions and limitations under the License. | |
14 | * | |
15 | * When distributing the software, include this License Header Notice in each | |
16 | * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt. | |
17 | * Sun designates this particular file as subject to the "Classpath" exception | |
18 | * as provided by Sun in the GPL Version 2 section of the License file that | |
19 | * accompanied this code. If applicable, add the following below the License | |
20 | * Header, with the fields enclosed by brackets [] replaced by your own | |
21 | * identifying information: "Portions Copyrighted [year] | |
22 | * [name of copyright owner]" | |
23 | * | |
24 | * Contributor(s): | |
25 | * | |
26 | * If you wish your version of this file to be governed by only the CDDL or | |
27 | * only the GPL Version 2, indicate your decision by adding "[Contributor] | |
28 | * elects to include this software in this distribution under the [CDDL or GPL | |
29 | * Version 2] license." If you don't indicate a single choice of license, a | |
30 | * recipient has the option to distribute your version of this file under | |
31 | * either the CDDL, the GPL Version 2 or to extend the choice of license to | |
32 | * its licensees as provided above. However, if you add GPL Version 2 code | |
33 | * and therefore, elected the GPL Version 2 license, then the option applies | |
34 | * only if the new code is made subject to such option by the copyright | |
35 | * holder. | |
36 | * | |
37 | */ | |
38 | package com.sun.grizzly.util; | |
39 | ||
40 | import com.sun.grizzly.Controller; | |
41 | import java.io.IOException; | |
42 | import java.nio.channels.Selector; | |
43 | import java.util.EmptyStackException; | |
44 | import java.util.Stack; | |
45 | import java.util.logging.Level; | |
46 | import java.util.logging.Logger; | |
47 | ||
48 | /** | |
49 | * Factory used to dispatch/share {@link Selector}. | |
50 | * | |
51 | * @author Scott Oaks | |
52 | * @author Jean-Francois Arcand | |
53 | */ | |
54 | 0 | public class SelectorFactory{ |
55 | ||
56 | public static final int DEFAULT_MAX_SELECTORS = 20; | |
57 | ||
58 | /** | |
59 | * The timeout before we exit. | |
60 | */ | |
61 | 1 | public static long timeout = 5000; |
62 | ||
63 | ||
64 | /** | |
65 | * The number of {@link Selector} to create. | |
66 | */ | |
67 | 1 | private static int maxSelectors = DEFAULT_MAX_SELECTORS; |
68 | ||
69 | ||
70 | /** | |
71 | * Cache of {@link Selector} | |
72 | */ | |
73 | 1 | private final static Stack<Selector> selectors = new Stack<Selector>(); |
74 | ||
75 | ||
76 | /** | |
77 | * have we created the Selector instances. | |
78 | */ | |
79 | 1 | private static boolean initialized = false; |
80 | ||
81 | /** | |
82 | * Set max selector pool size. | |
83 | * @param size max pool size | |
84 | */ | |
85 | public final static void setMaxSelectors(int size) throws IOException { | |
86 | 1 | synchronized(selectors) { |
87 | 1 | if (size > maxSelectors || !initialized) { |
88 | // if not initialized yet - grow cache by size | |
89 | 1 | if (!initialized) maxSelectors = 0; |
90 | ||
91 | 1 | grow(size); |
92 | 0 | } else if (size < maxSelectors) { |
93 | 0 | reduce(size); |
94 | } | |
95 | ||
96 | 1 | maxSelectors = size; |
97 | 1 | initialized = true; |
98 | 1 | } |
99 | 1 | } |
100 | ||
101 | /** | |
102 | * Returns max selector pool size | |
103 | * @return max pool size | |
104 | */ | |
105 | public final static int getMaxSelectors() { | |
106 | 0 | return maxSelectors; |
107 | } | |
108 | ||
109 | /** | |
110 | * Get a exclusive {@link Selector} | |
111 | * @return {@link Selector} | |
112 | */ | |
113 | public final static Selector getSelector() { | |
114 | 704 | synchronized(selectors) { |
115 | 704 | if (!initialized) { |
116 | try { | |
117 | 1 | setMaxSelectors(maxSelectors); |
118 | 0 | } catch (IOException e) { |
119 | 0 | Logger logger = Controller.logger(); |
120 | 0 | if (logger.isLoggable(Level.WARNING)) { |
121 | 0 | logger.log(Level.WARNING, "SelectorFactory lazy initialization", e); |
122 | } | |
123 | 1 | } |
124 | } | |
125 | ||
126 | 704 | Selector s = null; |
127 | try { | |
128 | 704 | if ( selectors.size() != 0 ) |
129 | 704 | s = selectors.pop(); |
130 | 704 | } catch (EmptyStackException ex){} |
131 | ||
132 | 704 | int attempts = 0; |
133 | try{ | |
134 | 704 | while (s == null && attempts < 2) { |
135 | 0 | selectors.wait(timeout); |
136 | try { | |
137 | 0 | if ( selectors.size() != 0 ) |
138 | 0 | s = selectors.pop(); |
139 | 0 | } catch (EmptyStackException ex){ |
140 | 0 | break; |
141 | 0 | } |
142 | 0 | attempts++; |
143 | } | |
144 | 704 | } catch (InterruptedException ex){} |
145 | 704 | return s; |
146 | 0 | } |
147 | } | |
148 | ||
149 | ||
150 | /** | |
151 | * Return the {@link Selector} to the cache | |
152 | * @param s {@link Selector} | |
153 | */ | |
154 | public final static void returnSelector(Selector s) { | |
155 | 704 | synchronized(selectors) { |
156 | 704 | selectors.push(s); |
157 | 704 | if (selectors.size() == 1) |
158 | 0 | selectors.notify(); |
159 | 704 | } |
160 | 704 | } |
161 | ||
162 | /** | |
163 | * Executes <code>Selector.selectNow()</code> and returns | |
164 | * the {@link Selector} to the cache | |
165 | */ | |
166 | public final static void selectNowAndReturnSelector(Selector s) { | |
167 | try { | |
168 | 704 | s.selectNow(); |
169 | 704 | returnSelector(s); |
170 | 0 | } catch(IOException e) { |
171 | 0 | Logger logger = Controller.logger(); |
172 | 0 | logger.log(Level.WARNING, |
173 | "Unexpected problem when releasing temporary Selector", e); | |
174 | try { | |
175 | 0 | s.close(); |
176 | 0 | } catch(IOException ee) { |
177 | // We are not interested | |
178 | 0 | } |
179 | ||
180 | try { | |
181 | 0 | reimburseSelector(); |
182 | 0 | } catch(IOException ee) { |
183 | 0 | logger.log(Level.WARNING, |
184 | "Problematic Selector could not be reimbursed!", ee); | |
185 | 0 | } |
186 | 704 | } |
187 | 704 | } |
188 | ||
189 | /** | |
190 | * Add Selector to the cache. | |
191 | * This method could be called to reimberse a lost or problematic Selector. | |
192 | * | |
193 | * @throws java.io.IOException | |
194 | */ | |
195 | public final static void reimburseSelector() throws IOException { | |
196 | 0 | returnSelector(createSelector()); |
197 | 0 | } |
198 | ||
199 | /** | |
200 | * Creeate Selector | |
201 | * @return Selector | |
202 | * @throws java.io.IOException | |
203 | */ | |
204 | protected static Selector createSelector() throws IOException { | |
205 | 20 | return Selector.open(); |
206 | } | |
207 | ||
208 | ||
209 | /** | |
210 | * Increase {@link Selector} pool size | |
211 | */ | |
212 | private static void grow(int size) throws IOException { | |
213 | 21 | for(int i=0; i<size - maxSelectors; i++) { |
214 | 20 | selectors.add(createSelector()); |
215 | } | |
216 | 1 | } |
217 | ||
218 | /** | |
219 | * Decrease {@link Selector} pool size | |
220 | */ | |
221 | private static void reduce(int size) { | |
222 | 0 | for(int i=0; i<maxSelectors - size; i++) { |
223 | try { | |
224 | 0 | Selector selector = selectors.pop(); |
225 | 0 | selector.close(); |
226 | 0 | } catch(IOException e) { |
227 | 0 | Logger logger = Controller.logger(); |
228 | 0 | if (logger.isLoggable(Level.FINE)) { |
229 | 0 | logger.log(Level.FINE, "SelectorFactory.reduce", e); |
230 | } | |
231 | 0 | } |
232 | } | |
233 | 0 | } |
234 | ||
235 | } |