1
2
3
4
5
6
7
8
9
10
11 package org.mule.providers.tcp.issues;
12
13 import java.io.IOException;
14 import java.net.BindException;
15 import java.net.InetSocketAddress;
16 import java.net.ServerSocket;
17 import java.net.Socket;
18
19 import junit.framework.TestCase;
20 import org.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 public class ReuseExperimentMule2067TestCase extends TestCase
51 {
52
53 private static final int NO_WAIT = -1;
54 private static final int PORT = 65432;
55 private static boolean NO_REUSE = false;
56 private static boolean REUSE = true;
57
58 private Log logger = LogFactory.getLog(getClass());
59
60 public void testReuse() throws IOException
61 {
62 repeatOpenCloseClientServer(1000, 10, PORT, 1, REUSE, false);
63 repeatOpenCloseClientServer(100, 10, PORT, 1, NO_REUSE, false);
64 }
65
66 public void testMeasureImprovement() throws IOException
67 {
68 measureMeanRunLength(10, 100, 10, PORT, 100, NO_REUSE);
69 measureMeanRunLength(10, 100, 10, PORT+10, 100, REUSE);
70 measureMeanRunLength(10, 100, 10, PORT+20, 10, NO_REUSE);
71 measureMeanRunLength(10, 100, 10, PORT+30, 10, REUSE);
72 measureMeanRunLength(10, 100, 10, PORT+40, 1, NO_REUSE);
73 measureMeanRunLength(10, 100, 10, PORT+50, 1, REUSE);
74 }
75
76 protected void measureMeanRunLength(int sampleSize, int numberOfRepeats, int numberOfConnections,
77 int port, long pause, boolean reuse)
78 throws IOException
79 {
80 logger.info("Measuring average run length for " + numberOfRepeats + " repeats " +
81 (reuse ? "with" : "without") + " reuse and a pause of " + pause + " ms");
82 int totalLength = 0;
83 long totalLengthSquared = 0;
84 for (int i = 0; i < sampleSize; ++i)
85 {
86 int length = repeatOpenCloseClientServer(numberOfRepeats, numberOfConnections, port+i, pause, reuse, true);
87 totalLength += length;
88 totalLengthSquared += length * length;
89 }
90 double mean = totalLength / (double) sampleSize;
91 double sd = Math.sqrt(totalLengthSquared / (double) sampleSize - mean * mean);
92 logger.info("Average run length: " + mean + " +/- " + sd);
93 }
94
95 protected int repeatOpenCloseClientServer(int numberOfRepeats, int numberOfConnections, int port,
96 long pause, boolean reuse, boolean noFail)
97 throws IOException
98 {
99 String message = "Repeating openCloseClientServer with pauses of " + pause + " ms "
100 + (reuse ? "with" : "without") + " reuse";
101 if (noFail)
102 {
103 logger.debug(message);
104 }
105 else
106 {
107 logger.info(message);
108 }
109 for (int i = 0; i < numberOfRepeats; i++)
110 {
111 if (0 != i)
112 {
113 pause(pause);
114 }
115 try
116 {
117 openCloseClientServer(numberOfConnections, port, reuse);
118 }
119 catch (BindException e)
120 {
121 if (noFail && e.getMessage().indexOf("Address already in use") > -1)
122 {
123 return i;
124 }
125 throw e;
126 }
127 }
128 return numberOfRepeats;
129 }
130
131 protected void openCloseClientServer(int numberOfConnections, int port, boolean reuse)
132 throws IOException
133 {
134 Server server = new Server(port, reuse);
135 try {
136 new Thread(server).start();
137 for (int i = 0; i < numberOfConnections; i++)
138 {
139 logger.debug("opening socket " + i);
140 Socket client = new Socket("localhost", port);
141 client.close();
142 }
143 }
144 finally
145 {
146 server.close();
147 }
148 }
149
150 protected void pause(long pause)
151 {
152 if (pause != NO_WAIT)
153 {
154 try
155 {
156 if (pause > 0)
157 {
158 Thread.sleep(pause);
159 }
160 }
161 catch (InterruptedException e)
162 {
163
164 }
165 }
166 }
167
168 protected static class Server implements Runnable
169 {
170
171 private Log logger = LogFactory.getLog(getClass());
172 private ServerSocket server;
173
174 public Server(int port, boolean reuse) throws IOException
175 {
176 server = new ServerSocket();
177 server.setReuseAddress(reuse);
178 server.bind(new InetSocketAddress("localhost", port));
179 }
180
181 public void run()
182 {
183 try
184 {
185 while (true)
186 {
187 Socket socket = server.accept();
188 socket.close();
189 }
190 }
191 catch (Exception e)
192 {
193 logger.debug("Expected - dirty closedown: " + e);
194 }
195 }
196
197 public void close() throws IOException
198 {
199 server.close();
200 server = null;
201 }
202 }
203
204 }