View Javadoc
1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the 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  class DefaultNioSocketChannelConfig extends DefaultSocketChannelConfig
34          implements NioSocketChannelConfig {
35  
36      private static final InternalLogger logger =
37          InternalLoggerFactory.getInstance(DefaultNioSocketChannelConfig.class);
38  
39      private static final ReceiveBufferSizePredictorFactory DEFAULT_PREDICTOR_FACTORY =
40          new AdaptiveReceiveBufferSizePredictorFactory();
41  
42      private volatile int writeBufferHighWaterMark = 64 * 1024;
43      private volatile int writeBufferLowWaterMark  = 32 * 1024;
44      private volatile ReceiveBufferSizePredictor predictor;
45      private volatile ReceiveBufferSizePredictorFactory predictorFactory = DEFAULT_PREDICTOR_FACTORY;
46      private volatile int writeSpinCount = 16;
47  
48      DefaultNioSocketChannelConfig(Socket socket) {
49          super(socket);
50      }
51  
52      @Override
53      public void setOptions(Map<String, Object> options) {
54          super.setOptions(options);
55          if (getWriteBufferHighWaterMark() < getWriteBufferLowWaterMark()) {
56              // Recover the integrity of the configuration with a sensible value.
57              setWriteBufferLowWaterMark0(getWriteBufferHighWaterMark() >>> 1);
58              if (logger.isWarnEnabled()) {
59                  // Notify the user about misconfiguration.
60                  logger.warn(
61                          "writeBufferLowWaterMark cannot be greater than " +
62                          "writeBufferHighWaterMark; setting to the half of the " +
63                          "writeBufferHighWaterMark.");
64              }
65          }
66      }
67  
68      @Override
69      public boolean setOption(String key, Object value) {
70          if (super.setOption(key, value)) {
71              return true;
72          }
73  
74          if ("writeBufferHighWaterMark".equals(key)) {
75              setWriteBufferHighWaterMark0(ConversionUtil.toInt(value));
76          } else if ("writeBufferLowWaterMark".equals(key)) {
77              setWriteBufferLowWaterMark0(ConversionUtil.toInt(value));
78          } else if ("writeSpinCount".equals(key)) {
79              setWriteSpinCount(ConversionUtil.toInt(value));
80          } else if ("receiveBufferSizePredictorFactory".equals(key)) {
81              setReceiveBufferSizePredictorFactory((ReceiveBufferSizePredictorFactory) value);
82          } else if ("receiveBufferSizePredictor".equals(key)) {
83              setReceiveBufferSizePredictor((ReceiveBufferSizePredictor) value);
84          } else {
85              return false;
86          }
87          return true;
88      }
89  
90      public int getWriteBufferHighWaterMark() {
91          return writeBufferHighWaterMark;
92      }
93  
94      public void setWriteBufferHighWaterMark(int writeBufferHighWaterMark) {
95          if (writeBufferHighWaterMark < getWriteBufferLowWaterMark()) {
96              throw new IllegalArgumentException(
97                      "writeBufferHighWaterMark cannot be less than " +
98                      "writeBufferLowWaterMark (" + getWriteBufferLowWaterMark() + "): " +
99                      writeBufferHighWaterMark);
100         }
101         setWriteBufferHighWaterMark0(writeBufferHighWaterMark);
102     }
103 
104     private void setWriteBufferHighWaterMark0(int writeBufferHighWaterMark) {
105         if (writeBufferHighWaterMark < 0) {
106             throw new IllegalArgumentException(
107                     "writeBufferHighWaterMark: " + writeBufferHighWaterMark);
108         }
109         this.writeBufferHighWaterMark = writeBufferHighWaterMark;
110     }
111 
112     public int getWriteBufferLowWaterMark() {
113         return writeBufferLowWaterMark;
114     }
115 
116     public void setWriteBufferLowWaterMark(int writeBufferLowWaterMark) {
117         if (writeBufferLowWaterMark > getWriteBufferHighWaterMark()) {
118             throw new IllegalArgumentException(
119                     "writeBufferLowWaterMark cannot be greater than " +
120                     "writeBufferHighWaterMark (" + getWriteBufferHighWaterMark() + "): " +
121                     writeBufferLowWaterMark);
122         }
123         setWriteBufferLowWaterMark0(writeBufferLowWaterMark);
124     }
125 
126     private void setWriteBufferLowWaterMark0(int writeBufferLowWaterMark) {
127         if (writeBufferLowWaterMark < 0) {
128             throw new IllegalArgumentException(
129                     "writeBufferLowWaterMark: " + writeBufferLowWaterMark);
130         }
131         this.writeBufferLowWaterMark = writeBufferLowWaterMark;
132     }
133 
134     public int getWriteSpinCount() {
135         return writeSpinCount;
136     }
137 
138     public void setWriteSpinCount(int writeSpinCount) {
139         if (writeSpinCount <= 0) {
140             throw new IllegalArgumentException(
141                     "writeSpinCount must be a positive integer.");
142         }
143         this.writeSpinCount = writeSpinCount;
144     }
145 
146     public ReceiveBufferSizePredictor getReceiveBufferSizePredictor() {
147         ReceiveBufferSizePredictor predictor = this.predictor;
148         if (predictor == null) {
149             try {
150                 this.predictor = predictor = getReceiveBufferSizePredictorFactory().getPredictor();
151             } catch (Exception e) {
152                 throw new ChannelException(
153                         "Failed to create a new " +
154                         ReceiveBufferSizePredictor.class.getSimpleName() + '.',
155                         e);
156             }
157         }
158         return predictor;
159     }
160 
161     public void setReceiveBufferSizePredictor(
162             ReceiveBufferSizePredictor predictor) {
163         if (predictor == null) {
164             throw new NullPointerException("predictor");
165         }
166         this.predictor = predictor;
167     }
168 
169     public ReceiveBufferSizePredictorFactory getReceiveBufferSizePredictorFactory() {
170         return predictorFactory;
171     }
172 
173     public void setReceiveBufferSizePredictorFactory(ReceiveBufferSizePredictorFactory predictorFactory) {
174         if (predictorFactory == null) {
175             throw new NullPointerException("predictorFactory");
176         }
177         this.predictorFactory = predictorFactory;
178     }
179 }