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  
69      @Override
70      public boolean setOption(String key, Object value) {
71          if (super.setOption(key, value)) {
72              return true;
73          }
74  
75          if (key.equals("writeBufferHighWaterMark")) {
76              setWriteBufferHighWaterMark0(ConversionUtil.toInt(value));
77          } else if (key.equals("writeBufferLowWaterMark")) {
78              setWriteBufferLowWaterMark0(ConversionUtil.toInt(value));
79          } else if (key.equals("writeSpinCount")) {
80              setWriteSpinCount(ConversionUtil.toInt(value));
81          } else if (key.equals("receiveBufferSizePredictorFactory")) {
82              setReceiveBufferSizePredictorFactory((ReceiveBufferSizePredictorFactory) value);
83          } else if (key.equals("receiveBufferSizePredictor")) {
84              setReceiveBufferSizePredictor((ReceiveBufferSizePredictor) value);
85          } else {
86              return false;
87          }
88          return true;
89      }
90  
91      public int getWriteBufferHighWaterMark() {
92          return writeBufferHighWaterMark;
93      }
94  
95      public void setWriteBufferHighWaterMark(int writeBufferHighWaterMark) {
96          if (writeBufferHighWaterMark < getWriteBufferLowWaterMark()) {
97              throw new IllegalArgumentException(
98                      "writeBufferHighWaterMark cannot be less than " +
99                      "writeBufferLowWaterMark (" + getWriteBufferLowWaterMark() + "): " +
100                     writeBufferHighWaterMark);
101         }
102         setWriteBufferHighWaterMark0(writeBufferHighWaterMark);
103     }
104 
105     private void setWriteBufferHighWaterMark0(int writeBufferHighWaterMark) {
106         if (writeBufferHighWaterMark < 0) {
107             throw new IllegalArgumentException(
108                     "writeBufferHighWaterMark: " + writeBufferHighWaterMark);
109         }
110         this.writeBufferHighWaterMark = writeBufferHighWaterMark;
111     }
112 
113     public int getWriteBufferLowWaterMark() {
114         return writeBufferLowWaterMark;
115     }
116 
117     public void setWriteBufferLowWaterMark(int writeBufferLowWaterMark) {
118         if (writeBufferLowWaterMark > getWriteBufferHighWaterMark()) {
119             throw new IllegalArgumentException(
120                     "writeBufferLowWaterMark cannot be greater than " +
121                     "writeBufferHighWaterMark (" + getWriteBufferHighWaterMark() + "): " +
122                     writeBufferLowWaterMark);
123         }
124         setWriteBufferLowWaterMark0(writeBufferLowWaterMark);
125     }
126 
127     private void setWriteBufferLowWaterMark0(int writeBufferLowWaterMark) {
128         if (writeBufferLowWaterMark < 0) {
129             throw new IllegalArgumentException(
130                     "writeBufferLowWaterMark: " + writeBufferLowWaterMark);
131         }
132         this.writeBufferLowWaterMark = writeBufferLowWaterMark;
133     }
134 
135     public int getWriteSpinCount() {
136         return writeSpinCount;
137     }
138 
139     public void setWriteSpinCount(int writeSpinCount) {
140         if (writeSpinCount <= 0) {
141             throw new IllegalArgumentException(
142                     "writeSpinCount must be a positive integer.");
143         }
144         this.writeSpinCount = writeSpinCount;
145     }
146 
147     public ReceiveBufferSizePredictor getReceiveBufferSizePredictor() {
148         ReceiveBufferSizePredictor predictor = this.predictor;
149         if (predictor == null) {
150             try {
151                 this.predictor = predictor = getReceiveBufferSizePredictorFactory().getPredictor();
152             } catch (Exception e) {
153                 throw new ChannelException(
154                         "Failed to create a new " +
155                         ReceiveBufferSizePredictor.class.getSimpleName() + '.',
156                         e);
157             }
158         }
159         return predictor;
160     }
161 
162     public void setReceiveBufferSizePredictor(
163             ReceiveBufferSizePredictor predictor) {
164         if (predictor == null) {
165             throw new NullPointerException("predictor");
166         }
167         this.predictor = predictor;
168     }
169 
170     public ReceiveBufferSizePredictorFactory getReceiveBufferSizePredictorFactory() {
171         return predictorFactory;
172     }
173 
174     public void setReceiveBufferSizePredictorFactory(ReceiveBufferSizePredictorFactory predictorFactory) {
175         if (predictorFactory == null) {
176             throw new NullPointerException("predictorFactory");
177         }
178         this.predictorFactory = predictorFactory;
179     }
180 }