1
2
3
4
5
6
7 package org.mule.transport.tcp.issues;
8
9 import org.mule.tck.junit4.AbstractMuleTestCase;
10
11 import java.io.IOException;
12 import java.net.BindException;
13 import java.net.InetSocketAddress;
14 import java.net.ServerSocket;
15 import java.net.Socket;
16
17 import org.apache.commons.logging.Log;
18 import org.apache.commons.logging.LogFactory;
19 import org.junit.Test;
20
21
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 public class ReuseExperimentMule2067TestCase extends AbstractMuleTestCase
49 {
50
51 private static final int NO_WAIT = -1;
52 private static final int PORT = 65432;
53 private static boolean NO_REUSE = false;
54 private static boolean REUSE = true;
55
56 private Log logger = LogFactory.getLog(getClass());
57
58 @Test
59 public void testReuse() throws IOException
60 {
61 repeatOpenCloseClientServer(1000, 10, PORT, 1, REUSE, false);
62 repeatOpenCloseClientServer(100, 10, PORT, 1, NO_REUSE, false);
63 }
64
65 @Test
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 synchronized(this)
157 {
158 if (pause > 0)
159 {
160 this.wait(pause);
161 }
162 }
163 }
164 catch (InterruptedException e)
165 {
166
167 }
168 }
169 }
170
171 protected static class Server implements Runnable
172 {
173
174 private Log logger = LogFactory.getLog(getClass());
175 private ServerSocket server;
176
177 public Server(int port, boolean reuse) throws IOException
178 {
179 server = new ServerSocket();
180 server.setReuseAddress(reuse);
181 server.bind(new InetSocketAddress("localhost", port));
182 }
183
184 public void run()
185 {
186 try
187 {
188 while (true)
189 {
190 Socket socket = server.accept();
191 socket.close();
192 }
193 }
194 catch (Exception e)
195 {
196 logger.debug("Expected - dirty closedown: " + e);
197 }
198 }
199
200 public void close() throws IOException
201 {
202 server.close();
203 server = null;
204 }
205 }
206
207 }