KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jgroups > protocols > AUTOCONF


1 // $Id: AUTOCONF.java,v 1.11 2005/04/07 15:03:20 belaban Exp $
2

3 package org.jgroups.protocols;
4
5 import org.jgroups.Event;
6 import org.jgroups.stack.Protocol;
7
8 import java.io.IOException JavaDoc;
9 import java.net.DatagramPacket JavaDoc;
10 import java.net.DatagramSocket JavaDoc;
11 import java.net.InetAddress JavaDoc;
12 import java.util.HashMap JavaDoc;
13 import java.util.Properties JavaDoc;
14
15
16 /**
17  * Senses the network configuration when it is initialized (in init()) and sends a CONFIG event up
18  * and down the stack. The CONFIG event contains a hashmap, with strings as keys (e.g. "frag_size")
19  * and Objects as values. Certain protocols can set some of their properties when receiving the CONFIG
20  * event.<br>
21  * This protocol should be placed above the transport protocol (e.g. UDP). It is not needed for TCP.<br>
22  * Example: senses the network send and receive buffers, plus the max size of a message to be sent and
23  * generates a CONFIG event containing "frag_size", "send_buf_size" and "receive_buf_size" keys.
24  *
25  * @author Bela Ban
26  */

27 public class AUTOCONF extends Protocol {
28     final HashMap JavaDoc config=new HashMap JavaDoc();
29     static int num_iterations=10; // to find optimal frag_size
30

31     /** Number of bytes to subtract from computed fragmentation size, due to (a) headers and
32      * (b) serialization overhead */

33     static int frag_overhead=1000;
34
35
36     public String JavaDoc getName() {
37         return "AUTOCONF";
38     }
39
40
41     public void init() throws Exception JavaDoc {
42         senseNetworkConfiguration();
43         if(log.isDebugEnabled()) log.debug("configuration is\n" + config);
44     }
45
46     public void start() throws Exception JavaDoc {
47         if(config != null && config.size() > 0) {
48             Event config_evt=new Event(Event.CONFIG, config);
49             passDown(config_evt);
50             passUp(config_evt);
51         }
52     }
53
54
55     /**
56      * Setup the Protocol instance acording to the configuration string
57      */

58     public boolean setProperties(Properties JavaDoc props) {
59         String JavaDoc str;
60
61         super.setProperties(props);
62         str=props.getProperty("num_iterations");
63         if(str != null) {
64             num_iterations=Integer.parseInt(str);
65             props.remove("num_iterations");
66         }
67
68         str=props.getProperty("frag_overhead");
69         if(str != null) {
70             frag_overhead=Integer.parseInt(str);
71             props.remove("frag_overhead");
72         }
73
74         if(props.size() > 0) {
75             System.err.println("AUTOCONF.setProperties(): the following properties are not recognized:");
76             props.list(System.out);
77             return false;
78         }
79         return true;
80     }
81
82
83     /**
84      * Leave empty: no up_thread will be created, but the up_thread of the neighbor below us will be used
85      */

86     public void startUpHandler() {
87         ;
88     }
89
90     /**
91      * Leave empty: no down_thread will be created, but the down_thread of the neighbor above us will be used
92      */

93     public void startDownHandler() {
94         ;
95     }
96
97
98     /* -------------------------------------- Private metods ------------------------------------------- */
99     void senseNetworkConfiguration() {
100         int max_frag_size=senseMaxFragSize();
101         if(max_frag_size <= 0) {
102             if(log.isErrorEnabled()) log.error("max_frag_size is invalid: " + max_frag_size);
103         }
104         else
105             config.put("frag_size", new Integer JavaDoc(max_frag_size));
106         senseMaxSendBufferSize(config);
107         senseMaxReceiveBufferSize(config);
108     }
109
110     public static int senseMaxFragSizeStatic() {
111         return new AUTOCONF().senseMaxFragSize();
112     }
113
114     /**
115      * Tries to find out the max number of bytes in a DatagramPacket we can send by sending increasingly
116      * larger packets, until there is an exception (e.g. java.io.IOException: message too long)
117      */

118     public int senseMaxFragSize() {
119         int max_send=32000;
120         int upper=8192;
121         int lower=0;
122         int highest_failed=-1;
123         DatagramSocket JavaDoc sock=null;
124         byte[] buf;
125         DatagramPacket JavaDoc packet;
126         InetAddress JavaDoc local_addr;
127
128
129         try {
130             sock=new DatagramSocket JavaDoc();
131             local_addr=InetAddress.getLocalHost();
132         }
133         catch(Exception JavaDoc ex) {
134             if(log.isWarnEnabled()) log.warn("failed creating DatagramSocket: " + ex);
135             return 0;
136         }
137
138         try {
139             upper=max_send;
140             for(int i=0; i < num_iterations && lower < upper; i++) { // iterations to approximate frag_size
141
try {
142                     buf=new byte[upper];
143                     // System.out.println("** upper=" + upper + " (lower=" + lower + ")");
144
packet=new DatagramPacket JavaDoc(buf, buf.length, local_addr, 9);
145                     sock.send(packet);
146                     lower=Math.max(lower, upper);
147                     upper=upper * 2;
148                     if(highest_failed > -1)
149                         upper=Math.min(highest_failed, upper);
150                 }
151                 catch(IOException JavaDoc io_ex) {
152                     if(highest_failed > -1)
153                         highest_failed=Math.min(highest_failed, upper); // never exceed max_upper
154
else
155                         highest_failed=upper;
156                     upper=(upper + lower) / 2;
157                 }
158                 catch(Throwable JavaDoc ex) {
159                     if(log.isWarnEnabled()) log.warn("exception=" + ex);
160                     break;
161                 }
162             }
163
164             /** Reduce the frag_size a bit to prevent packets that are too large (see bug #854887) */
165             lower-=frag_overhead;
166             if(log.isDebugEnabled()) log.debug("frag_size=" + lower);
167             return lower;
168         }
169         finally {
170             if(sock != null)
171                 sock.close();
172         }
173     }
174
175
176     void senseMaxSendBufferSize(HashMap JavaDoc map) {
177         DatagramSocket JavaDoc sock=null;
178         int max_size=4096, retval=max_size;
179
180         if(map != null && map.containsKey("frag_size)"))
181             max_size=((Integer JavaDoc)map.get("frag_size")).intValue();
182
183         try {
184             sock=new DatagramSocket JavaDoc();
185             while(max_size < 1000000) {
186                 sock.setSendBufferSize(max_size);
187                 if((retval=sock.getSendBufferSize()) < max_size)
188                     return;
189                 max_size*=2;
190             }
191         }
192         catch(Throwable JavaDoc ex) {
193             if(log.isErrorEnabled()) log.error("failed getting the max send buffer size: " + ex +
194                     ". Defaulting to " + retval);
195             return;
196         }
197         finally {
198             map.put("send_buf_size", new Integer JavaDoc(retval));
199         }
200     }
201
202
203
204     void senseMaxReceiveBufferSize(HashMap JavaDoc map) {
205         DatagramSocket JavaDoc sock=null;
206         int max_size=4096, retval=max_size;
207
208         try {
209             sock=new DatagramSocket JavaDoc();
210             while(max_size < 1000000) {
211                 sock.setReceiveBufferSize(max_size);
212                 if((retval=sock.getReceiveBufferSize()) < max_size)
213                     return;
214                 max_size*=2;
215             }
216         }
217         catch(Throwable JavaDoc ex) {
218             if(log.isErrorEnabled()) log.error("failed getting the max send buffer size: " + ex +
219                     ". Defaulting to " + retval);
220             return;
221         }
222         finally {
223             map.put("recv_buf_size", new Integer JavaDoc(retval));
224         }
225     }
226
227
228     /* ----------------------------------- End of Private metods --------------------------------------- */
229
230     public static void main(String JavaDoc[] args) {
231         int frag_size=new AUTOCONF().senseMaxFragSize();
232         System.out.println("frag_size: " + frag_size);
233     }
234
235 }
236
Popular Tags