##### Coverage Report - com.sun.grizzly.util.SelectorFactory

Classes in this File | Line Coverage | Branch Coverage | Complexity
SelectorFactory |
49 % | 37/75
36 % | 10/28
| 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 | 759 |
             synchronized(selectors) {
115 | 759 |
                 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 | 759 |
                 Selector s = null;
127 |  |
                 try {
128 | 759 |
                     if ( selectors.size() != 0 )
129 | 759 |
                         s = selectors.pop();
130 | 759 |
                 } catch (EmptyStackException ex){}
131 |  |
132 | 759 |
                 int attempts = 0;
133 |  |
                 try{
134 | 759 |
                     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 | 759 |
                 } catch (InterruptedException ex){}
145 | 759 |
                 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 | 759 |
             synchronized(selectors) {
156 | 759 |
                 selectors.push(s);
157 | 759 |
                 if (selectors.size() == 1)
158 | 0 |
                     selectors.notify();
159 | 759 |
             }
160 | 759 |
         }
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 | 759 |
                 s.selectNow();
169 | 759 |
                 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 | 759 |
             }
187 | 759 |
         }
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 |  |
     }