View Javadoc

1   /*
2    * Copyright 2009 Red Hat, Inc.
3    *
4    * Red Hat licenses this file to you under the Apache License, version 2.0
5    * (the "License"); you may not use this file except in compliance with the
6    * License.  You may obtain a copy of the License at:
7    *
8    *    http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package org.jboss.netty.channel.socket.nio;
17  
18  import java.net.Socket;
19  import java.util.Map;
20  
21  import org.jboss.netty.channel.AdaptiveReceiveBufferSizePredictorFactory;
22  import org.jboss.netty.channel.ChannelException;
23  import org.jboss.netty.channel.ReceiveBufferSizePredictor;
24  import org.jboss.netty.channel.ReceiveBufferSizePredictorFactory;
25  import org.jboss.netty.channel.socket.DefaultSocketChannelConfig;
26  import org.jboss.netty.logging.InternalLogger;
27  import org.jboss.netty.logging.InternalLoggerFactory;
28  import org.jboss.netty.util.internal.ConversionUtil;
29  
30  /**
31   * The default {@link NioSocketChannelConfig} implementation.
32   *
33   * @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
34   * @author <a href="http://gleamynode.net/">Trustin Lee</a>
35   *
36   * @version $Rev: 2087 $, $Date: 2010-01-27 00:41:16 +0900 (Wed, 27 Jan 2010) $
37   *
38   */
39  class DefaultNioSocketChannelConfig extends DefaultSocketChannelConfig
40          implements NioSocketChannelConfig {
41  
42      private static final InternalLogger logger =
43          InternalLoggerFactory.getInstance(DefaultNioSocketChannelConfig.class);
44  
45      private static final ReceiveBufferSizePredictorFactory DEFAULT_PREDICTOR_FACTORY =
46          new AdaptiveReceiveBufferSizePredictorFactory();
47  
48      private volatile int writeBufferHighWaterMark = 64 * 1024;
49      private volatile int writeBufferLowWaterMark  = 32 * 1024;
50      private volatile ReceiveBufferSizePredictor predictor;
51      private volatile ReceiveBufferSizePredictorFactory predictorFactory = DEFAULT_PREDICTOR_FACTORY;
52      private volatile int writeSpinCount = 16;
53  
54      DefaultNioSocketChannelConfig(Socket socket) {
55          super(socket);
56      }
57  
58      @Override
59      public void setOptions(Map<String, Object> options) {
60          super.setOptions(options);
61          if (getWriteBufferHighWaterMark() < getWriteBufferLowWaterMark()) {
62              // Recover the integrity of the configuration with a sensible value.
63              setWriteBufferLowWaterMark0(getWriteBufferHighWaterMark() >>> 1);
64              // Notify the user about misconfiguration.
65              logger.warn(
66                      "writeBufferLowWaterMark cannot be greater than " +
67                      "writeBufferHighWaterMark; setting to the half of the " +
68                      "writeBufferHighWaterMark.");
69          }
70      }
71  
72      @Override
73      public boolean setOption(String key, Object value) {
74          if (super.setOption(key, value)) {
75              return true;
76          }
77  
78          if (key.equals("writeBufferHighWaterMark")) {
79              setWriteBufferHighWaterMark0(ConversionUtil.toInt(value));
80          } else if (key.equals("writeBufferLowWaterMark")) {
81              setWriteBufferLowWaterMark0(ConversionUtil.toInt(value));
82          } else if (key.equals("writeSpinCount")) {
83              setWriteSpinCount(ConversionUtil.toInt(value));
84          } else if (key.equals("receiveBufferSizePredictorFactory")) {
85              setReceiveBufferSizePredictorFactory((ReceiveBufferSizePredictorFactory) value);
86          } else if (key.equals("receiveBufferSizePredictor")) {
87              setReceiveBufferSizePredictor((ReceiveBufferSizePredictor) value);
88          } else {
89              return false;
90          }
91          return true;
92      }
93  
94      public int getWriteBufferHighWaterMark() {
95          return writeBufferHighWaterMark;
96      }
97  
98      public void setWriteBufferHighWaterMark(int writeBufferHighWaterMark) {
99          if (writeBufferHighWaterMark < getWriteBufferLowWaterMark()) {
100             throw new IllegalArgumentException(
101                     "writeBufferHighWaterMark cannot be less than " +
102                     "writeBufferLowWaterMark (" + getWriteBufferLowWaterMark() + "): " +
103                     writeBufferHighWaterMark);
104         }
105         setWriteBufferHighWaterMark0(writeBufferHighWaterMark);
106     }
107 
108     private void setWriteBufferHighWaterMark0(int writeBufferHighWaterMark) {
109         if (writeBufferHighWaterMark < 0) {
110             throw new IllegalArgumentException(
111                     "writeBufferHighWaterMark: " + writeBufferHighWaterMark);
112         }
113         this.writeBufferHighWaterMark = writeBufferHighWaterMark;
114     }
115 
116     public int getWriteBufferLowWaterMark() {
117         return writeBufferLowWaterMark;
118     }
119 
120     public void setWriteBufferLowWaterMark(int writeBufferLowWaterMark) {
121         if (writeBufferLowWaterMark > getWriteBufferHighWaterMark()) {
122             throw new IllegalArgumentException(
123                     "writeBufferLowWaterMark cannot be greater than " +
124                     "writeBufferHighWaterMark (" + getWriteBufferHighWaterMark() + "): " +
125                     writeBufferLowWaterMark);
126         }
127         setWriteBufferLowWaterMark0(writeBufferLowWaterMark);
128     }
129 
130     private void setWriteBufferLowWaterMark0(int writeBufferLowWaterMark) {
131         if (writeBufferLowWaterMark < 0) {
132             throw new IllegalArgumentException(
133                     "writeBufferLowWaterMark: " + writeBufferLowWaterMark);
134         }
135         this.writeBufferLowWaterMark = writeBufferLowWaterMark;
136     }
137 
138     public int getWriteSpinCount() {
139         return writeSpinCount;
140     }
141 
142     public void setWriteSpinCount(int writeSpinCount) {
143         if (writeSpinCount <= 0) {
144             throw new IllegalArgumentException(
145                     "writeSpinCount must be a positive integer.");
146         }
147         this.writeSpinCount = writeSpinCount;
148     }
149 
150     public ReceiveBufferSizePredictor getReceiveBufferSizePredictor() {
151         ReceiveBufferSizePredictor predictor = this.predictor;
152         if (predictor == null) {
153             try {
154                 this.predictor = predictor = getReceiveBufferSizePredictorFactory().getPredictor();
155             } catch (Exception e) {
156                 throw new ChannelException(
157                         "Failed to create a new " +
158                         ReceiveBufferSizePredictor.class.getSimpleName() + '.',
159                         e);
160             }
161         }
162         return predictor;
163     }
164 
165     public void setReceiveBufferSizePredictor(
166             ReceiveBufferSizePredictor predictor) {
167         if (predictor == null) {
168             throw new NullPointerException("predictor");
169         }
170         this.predictor = predictor;
171     }
172 
173     public ReceiveBufferSizePredictorFactory getReceiveBufferSizePredictorFactory() {
174         return predictorFactory;
175     }
176 
177     public void setReceiveBufferSizePredictorFactory(ReceiveBufferSizePredictorFactory predictorFactory) {
178         if (predictorFactory == null) {
179             throw new NullPointerException("predictorFactory");
180         }
181         this.predictorFactory = predictorFactory;
182     }
183 }