1313import java .io .ByteArrayOutputStream ;
1414import java .io .IOException ;
1515import java .io .UnsupportedEncodingException ;
16+ import java .util .List ;
17+ import java .util .Vector ;
1618
1719import net .sf .j2s .ajax .HttpRequest ;
1820import 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 );
0 commit comments