Skip to content

Commit 8c785d7

Browse files
author
zhourenjian@gmail.com
committed
Support sending pipe live notification in one thread, so we can use Simple Pipe on server side to maintain lots of pipe connections to other servers.
1 parent 447060c commit 8c785d7

4 files changed

Lines changed: 127 additions & 60 deletions

File tree

sources/net.sf.j2s.ajax/ajaxcore/net/sf/j2s/ajax/ThreadUtils.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,14 @@ public static void runTask(Runnable r, String name, boolean daemon) {
2020
thread.setDaemon(daemon);
2121
thread.start();
2222
} else {
23-
aes.execute(r);
23+
try {
24+
aes.execute(r);
25+
} catch (Exception e) {
26+
//e.printStackTrace();
27+
Thread thread = new Thread(r, name);
28+
thread.setDaemon(daemon);
29+
thread.start();
30+
}
2431
}
2532
}
2633

@@ -30,7 +37,13 @@ public static void runTask(Runnable r) {
3037
Thread thread = new Thread(r);
3138
thread.start();
3239
} else {
33-
aes.execute(r);
40+
try {
41+
aes.execute(r);
42+
} catch (Exception e) {
43+
//e.printStackTrace();
44+
Thread thread = new Thread(r);
45+
thread.start();
46+
}
3447
}
3548
}
3649

sources/net.sf.j2s.ajax/ajaxpipe/net/sf/j2s/ajax/SimplePipeHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ public static void pipeIn(String key, SimpleSerializable[] ss) {
211211
continue;
212212
} else {
213213
int idx = list.indexOf(s);
214-
if (idx != -1 && idx > pipe.getLastBufferedIndex()) {
214+
if (idx != -1 && idx >= pipe.getLastBufferedIndex()) {
215215
// same object but with updated properties maybe!
216216
SimpleSerializable existed = list.get(idx);
217217
if (existed instanceof ISimpleCacheable) {

sources/net.sf.j2s.ajax/ajaxpipe/net/sf/j2s/ajax/SimplePipeRequest.java

Lines changed: 106 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import java.io.ByteArrayOutputStream;
1414
import java.io.IOException;
1515
import java.io.UnsupportedEncodingException;
16+
import java.util.List;
17+
import java.util.Vector;
1618

1719
import net.sf.j2s.ajax.HttpRequest;
1820
import net.sf.j2s.ajax.SimpleRPCRequest;
@@ -37,6 +39,15 @@ public static interface IHttpPipeRequestFactory extends IHttpRequestFactory {
3739

3840
}
3941

42+
@J2SIgnore
43+
private static Object notifyingMutex = new Object();
44+
45+
@J2SIgnore
46+
private static boolean notifyingThreadStarted = false;
47+
48+
@J2SIgnore
49+
private static List<SimplePipeRunnable> notifyingPipes = new Vector<SimplePipeRunnable>();
50+
4051
/**
4152
* Status of pipe: ok.
4253
*/
@@ -122,6 +133,8 @@ public static interface IHttpPipeRequestFactory extends IHttpRequestFactory {
122133

123134
private static int pipeMode = MODE_PIPE_CONTINUUM;
124135

136+
private static boolean queueNotifying = false;
137+
125138
private static long pipeQueryInterval = 1000;
126139

127140
static long pipeLiveNotifyInterval = 25000;
@@ -157,6 +170,12 @@ public static void switchToQueryMode(long ms) {
157170

158171
public static void switchToContinuumMode() {
159172
pipeMode = MODE_PIPE_CONTINUUM;
173+
queueNotifying = false;
174+
}
175+
176+
public static void switchToContinuumMode(boolean queue) {
177+
pipeMode = MODE_PIPE_CONTINUUM;
178+
queueNotifying = queue;
160179
}
161180

162181
/**
@@ -217,78 +236,108 @@ public void run() {
217236
* Be used in Java mode to keep the pipe live.
218237
*/
219238
@J2SIgnore
220-
static void keepPipeLive(final SimplePipeRunnable runnable) {
221-
runnable.updateStatus(true);
239+
static void keepPipeLive(final SimplePipeRunnable pipe) {
240+
pipe.updateStatus(true);
222241
if (getRequstMode() != MODE_LOCAL_JAVA_THREAD && getPipeMode() == MODE_PIPE_QUERY) {
223242
return;
224243
}
225244
//*
245+
boolean startingThread = false;
246+
synchronized (notifyingMutex) {
247+
if (!notifyingPipes.contains(pipe)) {
248+
pipe.lastPipeNotified = System.currentTimeMillis();
249+
notifyingPipes.add(pipe);
250+
}
251+
if (!notifyingThreadStarted) {
252+
startingThread = true;
253+
notifyingThreadStarted = true;
254+
}
255+
}
256+
if (!startingThread) {
257+
return;
258+
}
226259
ThreadUtils.runTask(new Runnable() {
227260

228261
public void run() {
229-
long lastLiveDetected = System.currentTimeMillis();
230-
do {
231-
long interval = pipeLiveNotifyInterval;
262+
while (true) {
263+
try {
264+
Thread.sleep(1000);
265+
} catch (InterruptedException e1) {
266+
//e1.printStackTrace();
267+
}
232268

233-
while (interval > 0) {
234-
try {
235-
Thread.sleep(Math.min(interval, 1000));
236-
interval -= 1000 + (runnable.pipeSequence - runnable.notifySequence) * 1000;
237-
} catch (InterruptedException e) {
238-
//e.printStackTrace();
269+
SimplePipeRunnable[] pipes = null;
270+
synchronized (notifyingMutex) {
271+
int size = notifyingPipes.size();
272+
if (size == 0) {
273+
notifyingThreadStarted = false;
274+
return;
239275
}
276+
pipes = notifyingPipes.toArray(new SimplePipeRunnable[size]);
277+
}
278+
long now = System.currentTimeMillis();
279+
for (int i = 0; i < pipes.length; i++) {
280+
final SimplePipeRunnable p = pipes[i];
240281
if (getRequstMode() == MODE_LOCAL_JAVA_THREAD) {
241-
if (!runnable.isPipeLive()) {
242-
break;
243-
}
244-
} else {
245-
SimplePipeRunnable pipeRunnable = SimplePipeHelper.getPipe(runnable.pipeKey);
246-
if (pipeRunnable == null || !pipeRunnable.isPipeLive()) {
247-
break;
282+
if (!p.isPipeLive()) {
283+
if (now - p.lastLiveDetected > p.pipeWaitClosingInterval()) {
284+
p.pipeDestroy(); // Pipe's server side destroying
285+
p.pipeClosed(); // Pipe's client side closing
286+
synchronized (notifyingMutex) {
287+
notifyingPipes.remove(p);
288+
}
289+
}
290+
} else if ((now - p.lastPipeNotified) * (2 + p.pipeSequence - p.notifySequence)
291+
< pipeLiveNotifyInterval + pipeLiveNotifyInterval) {
292+
// do nothing
293+
} else {
294+
p.keepPipeLive();
295+
p.lastPipeNotified = now;
296+
p.lastLiveDetected = System.currentTimeMillis();
248297
}
298+
continue; // end of MODE_LOCAL_JAVA_THREAD
249299
}
250-
}
251-
252-
if (getRequstMode() == MODE_LOCAL_JAVA_THREAD) {
253-
boolean pipeLive = runnable.isPipeLive();
254-
if (pipeLive) {
255-
runnable.keepPipeLive();
256-
lastLiveDetected = System.currentTimeMillis();
257-
} else {
258-
if (System.currentTimeMillis() - lastLiveDetected > runnable.pipeWaitClosingInterval()) {
259-
runnable.pipeDestroy(); // Pipe's server side destroying
260-
runnable.pipeClosed(); // Pipe's client side closing
261-
break;
300+
301+
SimplePipeRunnable r = SimplePipeHelper.getPipe(p.pipeKey);
302+
if (r == null || !r.isPipeLive()) {
303+
if (now - p.lastLiveDetected > p.pipeWaitClosingInterval()) {
304+
synchronized (notifyingMutex) {
305+
notifyingPipes.remove(p);
306+
}
262307
}
263-
}
264-
} else {
265-
SimplePipeRunnable r = SimplePipeHelper.getPipe(runnable.pipeKey);
266-
if (r != null && r.pipeSequence != r.notifySequence) {
267-
HttpRequest request = getRequest();
268-
String pipeKey = runnable.pipeKey;
269-
String pipeMethod = runnable.getPipeMethod();
270-
String pipeURL = runnable.getPipeURL();
271-
long sequence = runnable.pipeSequence;
308+
} else if ((now - p.lastPipeNotified) * (2 + p.pipeSequence - p.notifySequence)
309+
< pipeLiveNotifyInterval + pipeLiveNotifyInterval) {
310+
// do nothing
311+
} else if (r.pipeSequence != r.notifySequence) {
312+
p.lastPipeNotified = now;
313+
final HttpRequest request = getRequest();
314+
final String pipeKey = p.pipeKey;
315+
final long sequence = p.pipeSequence;
272316
String pipeRequestData = constructRequest(pipeKey, PIPE_TYPE_NOTIFY, sequence);
273-
sendRequest(request, pipeMethod, pipeURL, pipeRequestData, false);
274-
String response = request.getResponseText();
275-
if (response != null && runnable.notifySequence < sequence) {
276-
runnable.notifySequence = sequence;
277-
}
278-
if (response != null && response.indexOf("\"" + PIPE_STATUS_LOST + "\"") != -1) {
279-
runnable.pipeAlive = false;
280-
runnable.pipeLost();
281-
SimplePipeHelper.removePipe(pipeKey);
282-
// may need to inform user that connection is already lost!
283-
break;
284-
} else {
285-
runnable.updateStatus(true);
286-
}
287-
} else {
288-
break;
317+
request.registerOnReadyStateChange(new XHRCallbackAdapter() {
318+
public void onLoaded() {
319+
String response = request.getResponseText();
320+
if (response != null && p.notifySequence < sequence) {
321+
p.notifySequence = sequence;
322+
}
323+
if (response != null && response.indexOf("\"" + PIPE_STATUS_LOST + "\"") != -1) {
324+
p.pipeAlive = false;
325+
p.pipeLost();
326+
SimplePipeHelper.removePipe(pipeKey);
327+
// may need to inform user that connection is already lost!
328+
synchronized (notifyingMutex) {
329+
notifyingPipes.remove(p);
330+
}
331+
} else {
332+
p.lastLiveDetected = System.currentTimeMillis();
333+
p.updateStatus(true);
334+
}
335+
}
336+
});
337+
sendRequest(request, p.getPipeMethod(), p.getPipeURL(), pipeRequestData, pipes.length == 1 ? false : queueNotifying);
289338
}
290-
}
291-
} while (true);
339+
} // end of pipes for-loop
340+
} // end of while true
292341
}
293342

294343
}, "Pipe Live Notifier Thread", true);

sources/net.sf.j2s.ajax/ajaxpipe/net/sf/j2s/ajax/SimplePipeRunnable.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ public abstract class SimplePipeRunnable extends SimpleRPCRunnable {
5353
@J2SIgnore
5454
long lastLiveDetected;
5555

56+
@J2SIgnore
57+
long lastPipeNotified;
58+
5659
@J2SIgnore
5760
long lastHash;
5861

@@ -130,6 +133,8 @@ public String getPipeMethod() {
130133

131134
@Override
132135
public void ajaxIn() {
136+
pipeSequence = 1;
137+
notifySequence = 1;
133138
pipeInit();
134139
}
135140

0 commit comments

Comments
 (0)