PageRenderTime 104ms CodeModel.GetById 17ms RepoModel.GetById 3ms app.codeStats 1ms

/projects/tomcat-7.0.2/java/org/apache/tomcat/util/net/NioSelectorPool.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 304 lines | 204 code | 34 blank | 66 comment | 75 complexity | 34403a38ca894dd1735a2ee400208259 MD5 | raw file
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package org.apache.tomcat.util.net;
  18. import java.io.EOFException;
  19. import java.io.IOException;
  20. import java.net.SocketTimeoutException;
  21. import java.nio.ByteBuffer;
  22. import java.nio.channels.SelectionKey;
  23. import java.nio.channels.Selector;
  24. import java.util.NoSuchElementException;
  25. import java.util.concurrent.ConcurrentLinkedQueue;
  26. import java.util.concurrent.atomic.AtomicInteger;
  27. import org.apache.juli.logging.Log;
  28. import org.apache.juli.logging.LogFactory;
  29. import org.apache.tomcat.util.MutableInteger;
  30. /**
  31. *
  32. * Thread safe non blocking selector pool
  33. * @author Filip Hanik
  34. * @version 1.0
  35. * @since 6.0
  36. */
  37. public class NioSelectorPool {
  38. public NioSelectorPool() {
  39. }
  40. protected static int threadCount = 0;
  41. private static final Log log = LogFactory.getLog(NioSelectorPool.class);
  42. protected final static boolean SHARED =
  43. Boolean.valueOf(System.getProperty("org.apache.tomcat.util.net.NioSelectorShared", "true")).booleanValue();
  44. protected NioBlockingSelector blockingSelector;
  45. protected Selector SHARED_SELECTOR;
  46. protected int maxSelectors = 200;
  47. protected long sharedSelectorTimeout = 30000;
  48. protected int maxSpareSelectors = -1;
  49. protected boolean enabled = true;
  50. protected AtomicInteger active = new AtomicInteger(0);
  51. protected AtomicInteger spare = new AtomicInteger(0);
  52. protected ConcurrentLinkedQueue<Selector> selectors =
  53. new ConcurrentLinkedQueue<Selector>();
  54. protected Selector getSharedSelector() throws IOException {
  55. if (SHARED && SHARED_SELECTOR == null) {
  56. synchronized ( NioSelectorPool.class ) {
  57. if ( SHARED_SELECTOR == null ) {
  58. SHARED_SELECTOR = Selector.open();
  59. log.info("Using a shared selector for servlet write/read");
  60. }
  61. }
  62. }
  63. return SHARED_SELECTOR;
  64. }
  65. public Selector get() throws IOException{
  66. if ( SHARED ) {
  67. return getSharedSelector();
  68. }
  69. if ( (!enabled) || active.incrementAndGet() >= maxSelectors ) {
  70. if ( enabled ) active.decrementAndGet();
  71. return null;
  72. }
  73. Selector s = null;
  74. try {
  75. s = selectors.size()>0?selectors.poll():null;
  76. if (s == null) s = Selector.open();
  77. else spare.decrementAndGet();
  78. }catch (NoSuchElementException x ) {
  79. try {s = Selector.open();}catch (IOException iox){}
  80. } finally {
  81. if ( s == null ) active.decrementAndGet();//we were unable to find a selector
  82. }
  83. return s;
  84. }
  85. public void put(Selector s) throws IOException {
  86. if ( SHARED ) return;
  87. if ( enabled ) active.decrementAndGet();
  88. if ( enabled && (maxSpareSelectors==-1 || spare.get() < Math.min(maxSpareSelectors,maxSelectors)) ) {
  89. spare.incrementAndGet();
  90. selectors.offer(s);
  91. }
  92. else s.close();
  93. }
  94. public void close() throws IOException {
  95. enabled = false;
  96. Selector s;
  97. while ( (s = selectors.poll()) != null ) s.close();
  98. spare.set(0);
  99. active.set(0);
  100. if (blockingSelector!=null) {
  101. blockingSelector.close();
  102. }
  103. if ( SHARED && getSharedSelector()!=null ) {
  104. getSharedSelector().close();
  105. SHARED_SELECTOR = null;
  106. }
  107. }
  108. public void open() throws IOException {
  109. enabled = true;
  110. getSharedSelector();
  111. if (SHARED) {
  112. blockingSelector = new NioBlockingSelector();
  113. blockingSelector.open(getSharedSelector());
  114. }
  115. }
  116. /**
  117. * Performs a blocking write using the bytebuffer for data to be written and a selector to block.
  118. * If the <code>selector</code> parameter is null, then it will perform a busy write that could
  119. * take up a lot of CPU cycles.
  120. * @param buf ByteBuffer - the buffer containing the data, we will write as long as <code>(buf.hasRemaining()==true)</code>
  121. * @param socket SocketChannel - the socket to write data to
  122. * @param selector Selector - the selector to use for blocking, if null then a busy write will be initiated
  123. * @param writeTimeout long - the timeout for this write operation in milliseconds, -1 means no timeout
  124. * @return int - returns the number of bytes written
  125. * @throws EOFException if write returns -1
  126. * @throws SocketTimeoutException if the write times out
  127. * @throws IOException if an IO Exception occurs in the underlying socket logic
  128. */
  129. public int write(ByteBuffer buf, NioChannel socket, Selector selector, long writeTimeout) throws IOException {
  130. return write(buf,socket,selector,writeTimeout,true,null);
  131. }
  132. public int write(ByteBuffer buf, NioChannel socket, Selector selector,
  133. long writeTimeout, boolean block,MutableInteger lastWrite) throws IOException {
  134. if ( SHARED && block ) {
  135. return blockingSelector.write(buf,socket,writeTimeout,lastWrite);
  136. }
  137. SelectionKey key = null;
  138. int written = 0;
  139. boolean timedout = false;
  140. int keycount = 1; //assume we can write
  141. long time = System.currentTimeMillis(); //start the timeout timer
  142. try {
  143. while ( (!timedout) && buf.hasRemaining() ) {
  144. int cnt = 0;
  145. if ( keycount > 0 ) { //only write if we were registered for a write
  146. cnt = socket.write(buf); //write the data
  147. if (lastWrite!=null) lastWrite.set(cnt);
  148. if (cnt == -1) throw new EOFException();
  149. written += cnt;
  150. if (cnt > 0) {
  151. time = System.currentTimeMillis(); //reset our timeout timer
  152. continue; //we successfully wrote, try again without a selector
  153. }
  154. if (cnt==0 && (!block)) break; //don't block
  155. }
  156. if ( selector != null ) {
  157. //register OP_WRITE to the selector
  158. if (key==null) key = socket.getIOChannel().register(selector, SelectionKey.OP_WRITE);
  159. else key.interestOps(SelectionKey.OP_WRITE);
  160. keycount = selector.select(writeTimeout);
  161. }
  162. if (writeTimeout > 0 && (selector == null || keycount == 0) ) timedout = (System.currentTimeMillis()-time)>=writeTimeout;
  163. }//while
  164. if ( timedout ) throw new SocketTimeoutException();
  165. } finally {
  166. if (key != null) {
  167. key.cancel();
  168. if (selector != null) selector.selectNow();//removes the key from this selector
  169. }
  170. }
  171. return written;
  172. }
  173. /**
  174. * Performs a blocking read using the bytebuffer for data to be read and a selector to block.
  175. * If the <code>selector</code> parameter is null, then it will perform a busy read that could
  176. * take up a lot of CPU cycles.
  177. * @param buf ByteBuffer - the buffer containing the data, we will read as until we have read at least one byte or we timed out
  178. * @param socket SocketChannel - the socket to write data to
  179. * @param selector Selector - the selector to use for blocking, if null then a busy read will be initiated
  180. * @param readTimeout long - the timeout for this read operation in milliseconds, -1 means no timeout
  181. * @return int - returns the number of bytes read
  182. * @throws EOFException if read returns -1
  183. * @throws SocketTimeoutException if the read times out
  184. * @throws IOException if an IO Exception occurs in the underlying socket logic
  185. */
  186. public int read(ByteBuffer buf, NioChannel socket, Selector selector, long readTimeout) throws IOException {
  187. return read(buf,socket,selector,readTimeout,true);
  188. }
  189. /**
  190. * Performs a read using the bytebuffer for data to be read and a selector to register for events should
  191. * you have the block=true.
  192. * If the <code>selector</code> parameter is null, then it will perform a busy read that could
  193. * take up a lot of CPU cycles.
  194. * @param buf ByteBuffer - the buffer containing the data, we will read as until we have read at least one byte or we timed out
  195. * @param socket SocketChannel - the socket to write data to
  196. * @param selector Selector - the selector to use for blocking, if null then a busy read will be initiated
  197. * @param readTimeout long - the timeout for this read operation in milliseconds, -1 means no timeout
  198. * @param block - true if you want to block until data becomes available or timeout time has been reached
  199. * @return int - returns the number of bytes read
  200. * @throws EOFException if read returns -1
  201. * @throws SocketTimeoutException if the read times out
  202. * @throws IOException if an IO Exception occurs in the underlying socket logic
  203. */
  204. public int read(ByteBuffer buf, NioChannel socket, Selector selector, long readTimeout, boolean block) throws IOException {
  205. if ( SHARED && block ) {
  206. return blockingSelector.read(buf,socket,readTimeout);
  207. }
  208. SelectionKey key = null;
  209. int read = 0;
  210. boolean timedout = false;
  211. int keycount = 1; //assume we can write
  212. long time = System.currentTimeMillis(); //start the timeout timer
  213. try {
  214. while ( (!timedout) ) {
  215. int cnt = 0;
  216. if ( keycount > 0 ) { //only read if we were registered for a read
  217. cnt = socket.read(buf);
  218. if (cnt == -1) throw new EOFException();
  219. read += cnt;
  220. if (cnt > 0) continue; //read some more
  221. if (cnt==0 && (read>0 || (!block) ) ) break; //we are done reading
  222. }
  223. if ( selector != null ) {//perform a blocking read
  224. //register OP_WRITE to the selector
  225. if (key==null) key = socket.getIOChannel().register(selector, SelectionKey.OP_READ);
  226. else key.interestOps(SelectionKey.OP_READ);
  227. keycount = selector.select(readTimeout);
  228. }
  229. if (readTimeout > 0 && (selector == null || keycount == 0) ) timedout = (System.currentTimeMillis()-time)>=readTimeout;
  230. }//while
  231. if ( timedout ) throw new SocketTimeoutException();
  232. } finally {
  233. if (key != null) {
  234. key.cancel();
  235. if (selector != null) selector.selectNow();//removes the key from this selector
  236. }
  237. }
  238. return read;
  239. }
  240. public void setMaxSelectors(int maxSelectors) {
  241. this.maxSelectors = maxSelectors;
  242. }
  243. public void setMaxSpareSelectors(int maxSpareSelectors) {
  244. this.maxSpareSelectors = maxSpareSelectors;
  245. }
  246. public void setEnabled(boolean enabled) {
  247. this.enabled = enabled;
  248. }
  249. public void setSharedSelectorTimeout(long sharedSelectorTimeout) {
  250. this.sharedSelectorTimeout = sharedSelectorTimeout;
  251. }
  252. public int getMaxSelectors() {
  253. return maxSelectors;
  254. }
  255. public int getMaxSpareSelectors() {
  256. return maxSpareSelectors;
  257. }
  258. public boolean isEnabled() {
  259. return enabled;
  260. }
  261. public long getSharedSelectorTimeout() {
  262. return sharedSelectorTimeout;
  263. }
  264. public ConcurrentLinkedQueue<Selector> getSelectors() {
  265. return selectors;
  266. }
  267. public AtomicInteger getSpare() {
  268. return spare;
  269. }
  270. }