KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > corba > se > impl > oa > poa > POAManagerImpl


1 /*
2  * @(#)POAManagerImpl.java 1.22 04/06/21
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package com.sun.corba.se.impl.oa.poa;
9
10 import java.util.Iterator JavaDoc;
11 import java.util.Collections JavaDoc;
12 import java.util.Set JavaDoc;
13 import java.util.HashSet JavaDoc;
14
15 import org.omg.CORBA.LocalObject JavaDoc;
16 import org.omg.CORBA.CompletionStatus JavaDoc ;
17
18 import org.omg.PortableServer.POAManager JavaDoc;
19 import org.omg.PortableServer.POAManagerPackage.State JavaDoc;
20 import org.omg.PortableServer.POA JavaDoc;
21
22 import org.omg.PortableInterceptor.DISCARDING JavaDoc ;
23 import org.omg.PortableInterceptor.ACTIVE JavaDoc ;
24 import org.omg.PortableInterceptor.HOLDING JavaDoc ;
25 import org.omg.PortableInterceptor.INACTIVE JavaDoc ;
26 import org.omg.PortableInterceptor.NON_EXISTENT JavaDoc ;
27
28 import com.sun.corba.se.spi.protocol.PIHandler ;
29
30 import com.sun.corba.se.impl.logging.POASystemException ;
31
32 import com.sun.corba.se.impl.orbutil.ORBUtility ;
33
34 /** POAManagerImpl is the implementation of the POAManager interface.
35  * Its public methods are activate(), hold_requests(), discard_requests()
36  * and deactivate().
37  */

38
39 public class POAManagerImpl extends org.omg.CORBA.LocalObject JavaDoc implements
40     POAManager JavaDoc
41 {
42     private final POAFactory factory ; // factory which contains global state
43
// for all POAManagers
44
private PIHandler pihandler ; // for adapterManagerStateChanged
45
private State JavaDoc state; // current state of this POAManager
46
private Set JavaDoc poas = new HashSet JavaDoc(4) ; // all poas controlled by this POAManager
47
private int nInvocations=0; // Number of invocations in progress
48
private int nWaiters=0; // Number of threads waiting for
49
// invocations to complete
50
private int myId = 0 ; // This POAManager's ID
51
private boolean debug ;
52     private boolean explicitStateChange ; // initially false, set true as soon as
53
// one of activate, hold_request,
54
// discard_request, or deactivate is called.
55

56     private String JavaDoc stateToString( State JavaDoc state )
57     {
58     switch (state.value()) {
59         case State._HOLDING : return "State[HOLDING]" ;
60         case State._ACTIVE : return "State[ACTIVE]" ;
61         case State._DISCARDING : return "State[DISCARDING]" ;
62         case State._INACTIVE : return "State[INACTIVE]" ;
63     }
64
65     return "State[UNKNOWN]" ;
66     }
67
68     public String JavaDoc toString()
69     {
70     return "POAManagerImpl[myId=" + myId +
71         " state=" + stateToString(state) +
72         " nInvocations=" + nInvocations +
73         " nWaiters=" + nWaiters + "]" ;
74     }
75
76     POAFactory getFactory()
77     {
78     return factory ;
79     }
80
81     PIHandler getPIHandler()
82     {
83     return pihandler ;
84     }
85
86     private void countedWait()
87     {
88     try {
89         if (debug) {
90         ORBUtility.dprint( this, "Calling countedWait on POAManager " +
91             this + " nWaiters=" + nWaiters ) ;
92         }
93
94         nWaiters++ ;
95         wait();
96     } catch ( java.lang.InterruptedException JavaDoc ex ) {
97         // NOP
98
} finally {
99         nWaiters-- ;
100
101         if (debug) {
102         ORBUtility.dprint( this, "Exiting countedWait on POAManager " +
103             this + " nWaiters=" + nWaiters ) ;
104         }
105     }
106     }
107
108     private void notifyWaiters()
109     {
110     if (debug) {
111         ORBUtility.dprint( this, "Calling notifyWaiters on POAManager " +
112         this + " nWaiters=" + nWaiters ) ;
113     }
114
115     if (nWaiters >0)
116         notifyAll() ;
117     }
118
119     public int getManagerId()
120     {
121     return myId ;
122     }
123
124     POAManagerImpl( POAFactory factory, PIHandler pihandler )
125     {
126     this.factory = factory ;
127         factory.addPoaManager(this);
128     this.pihandler = pihandler ;
129     myId = factory.newPOAManagerId() ;
130     state = State.HOLDING;
131     debug = factory.getORB().poaDebugFlag ;
132     explicitStateChange = false ;
133
134     if (debug) {
135         ORBUtility.dprint( this, "Creating POAManagerImpl " + this ) ;
136     }
137     }
138
139     synchronized void addPOA(POA JavaDoc poa)
140     {
141     // XXX This is probably not the correct error
142
if (state.value() == State._INACTIVE) {
143         POASystemException wrapper = factory.getWrapper();
144         throw wrapper.addPoaInactive( CompletionStatus.COMPLETED_NO ) ;
145     }
146         
147         poas.add(poa);
148     }
149
150     synchronized void removePOA(POA JavaDoc poa)
151     {
152         poas.remove(poa);
153         if ( poas.isEmpty() ) {
154             factory.removePoaManager(this);
155     }
156     }
157
158     public short getORTState()
159     {
160     switch (state.value()) {
161         case State._HOLDING : return HOLDING.value ;
162         case State._ACTIVE : return ACTIVE.value ;
163         case State._INACTIVE : return INACTIVE.value ;
164         case State._DISCARDING : return DISCARDING.value ;
165         default : return NON_EXISTENT.value ;
166     }
167     }
168
169 /****************************************************************************
170  * The following four public methods are used to change the POAManager's state.
171  *
172  * A note on the design of synchronization code:
173  * There are 4 places where a thread would need to wait for a condition:
174  * - in hold_requests, discard_requests, deactivate, enter
175  * There are 5 places where a thread notifies a condition:
176  * - in activate, hold_requests, discard_requests, deactivate, exit
177  *
178  * Since each notify needs to awaken waiters in several of the 4 places,
179  * and since wait() in Java has the nice property of releasing the lock
180  * on its monitor before sleeping, it seemed simplest to have just one
181  * monitor object: "this". Thus all notifies will awaken all waiters.
182  * On waking up, each waiter verifies that the condition it was waiting
183  * for is satisfied, otherwise it goes back into a wait().
184  *
185  ****************************************************************************/

186
187     /**
188      * <code>activate</code>
189      * <b>Spec: pages 3-14 thru 3-18</b>
190      */

191     public synchronized void activate()
192         throws org.omg.PortableServer.POAManagerPackage.AdapterInactive JavaDoc
193     {
194     explicitStateChange = true ;
195
196     if (debug) {
197         ORBUtility.dprint( this,
198         "Calling activate on POAManager " + this ) ;
199     }
200
201     try {
202         if ( state.value() == State._INACTIVE )
203         throw new org.omg.PortableServer.POAManagerPackage.AdapterInactive JavaDoc();
204
205         // set the state to ACTIVE
206
state = State.ACTIVE;
207         
208         pihandler.adapterManagerStateChanged( myId, getORTState() ) ;
209
210         // Notify any invocations that were waiting because the previous
211
// state was HOLDING, as well as notify any threads that were waiting
212
// inside hold_requests() or discard_requests().
213
notifyWaiters();
214     } finally {
215         if (debug) {
216         ORBUtility.dprint( this,
217             "Exiting activate on POAManager " + this ) ;
218         }
219     }
220     }
221
222     /**
223      * <code>hold_requests</code>
224      * <b>Spec: pages 3-14 thru 3-18</b>
225      */

226     public synchronized void hold_requests(boolean wait_for_completion)
227         throws org.omg.PortableServer.POAManagerPackage.AdapterInactive JavaDoc
228     {
229     explicitStateChange = true ;
230
231     if (debug) {
232         ORBUtility.dprint( this,
233         "Calling hold_requests on POAManager " + this ) ;
234     }
235
236     try {
237         if ( state.value() == State._INACTIVE )
238         throw new org.omg.PortableServer.POAManagerPackage.AdapterInactive JavaDoc();
239         // set the state to HOLDING
240
state = State.HOLDING;
241
242         pihandler.adapterManagerStateChanged( myId, getORTState() ) ;
243
244         // Notify any threads that were waiting in the wait() inside
245
// discard_requests. This will cause discard_requests to return
246
// (which is in conformance with the spec).
247
notifyWaiters();
248
249         if ( wait_for_completion ) {
250         while ( state.value() == State._HOLDING && nInvocations > 0 ) {
251             countedWait() ;
252         }
253         }
254     } finally {
255         if (debug) {
256         ORBUtility.dprint( this,
257             "Exiting hold_requests on POAManager " + this ) ;
258         }
259     }
260     }
261
262     /**
263      * <code>discard_requests</code>
264      * <b>Spec: pages 3-14 thru 3-18</b>
265      */

266     public synchronized void discard_requests(boolean wait_for_completion)
267         throws org.omg.PortableServer.POAManagerPackage.AdapterInactive JavaDoc
268     {
269     explicitStateChange = true ;
270
271     if (debug) {
272         ORBUtility.dprint( this,
273         "Calling hold_requests on POAManager " + this ) ;
274     }
275      
276     try {
277         if ( state.value() == State._INACTIVE )
278         throw new org.omg.PortableServer.POAManagerPackage.AdapterInactive JavaDoc();
279
280         // set the state to DISCARDING
281
state = State.DISCARDING;
282
283         pihandler.adapterManagerStateChanged( myId, getORTState() ) ;
284
285         // Notify any invocations that were waiting because the previous
286
// state was HOLDING. Those invocations will henceforth be rejected with
287
// a TRANSIENT exception. Also notify any threads that were waiting
288
// inside hold_requests().
289
notifyWaiters();
290
291         if ( wait_for_completion ) {
292         while ( state.value() == State._DISCARDING && nInvocations > 0 ) {
293             countedWait() ;
294         }
295         }
296     } finally {
297         if (debug) {
298         ORBUtility.dprint( this,
299             "Exiting hold_requests on POAManager " + this ) ;
300         }
301     }
302     }
303
304     /**
305      * <code>deactivate</code>
306      * <b>Spec: pages 3-14 thru 3-18</b>
307      * Note: INACTIVE is a permanent state.
308      */

309
310     public void deactivate(boolean etherealize_objects, boolean wait_for_completion)
311         throws org.omg.PortableServer.POAManagerPackage.AdapterInactive JavaDoc
312     {
313     explicitStateChange = true ;
314
315     try {
316         synchronized( this ) {
317         if (debug) {
318             ORBUtility.dprint( this,
319             "Calling deactivate on POAManager " + this ) ;
320         }
321
322         if ( state.value() == State._INACTIVE )
323             throw new org.omg.PortableServer.POAManagerPackage.AdapterInactive JavaDoc();
324
325         state = State.INACTIVE;
326
327         pihandler.adapterManagerStateChanged( myId, getORTState() ) ;
328
329         // Notify any invocations that were waiting because the previous
330
// state was HOLDING. Those invocations will then be rejected with
331
// an OBJ_ADAPTER exception. Also notify any threads that were waiting
332
// inside hold_requests() or discard_requests().
333
notifyWaiters();
334         }
335
336         POAManagerDeactivator deactivator = new POAManagerDeactivator( this,
337         etherealize_objects, debug ) ;
338
339         if (wait_for_completion)
340         deactivator.run() ;
341         else {
342         Thread JavaDoc thr = new Thread JavaDoc(deactivator) ;
343         thr.start() ;
344         }
345     } finally {
346         synchronized(this) {
347         if (debug) {
348             ORBUtility.dprint( this,
349             "Exiting deactivate on POAManager " + this ) ;
350         }
351         }
352     }
353     }
354
355     private class POAManagerDeactivator implements Runnable JavaDoc
356     {
357     private boolean etherealize_objects ;
358     private POAManagerImpl pmi ;
359     private boolean debug ;
360
361     POAManagerDeactivator( POAManagerImpl pmi, boolean etherealize_objects,
362         boolean debug )
363     {
364         this.etherealize_objects = etherealize_objects ;
365         this.pmi = pmi ;
366         this.debug = debug ;
367     }
368
369     public void run()
370     {
371         try {
372         synchronized (pmi) {
373             if (debug) {
374             ORBUtility.dprint( this,
375                 "Calling run with etherealize_objects=" +
376                 etherealize_objects + " pmi=" + pmi ) ;
377             }
378
379             while ( pmi.nInvocations > 0 ) {
380             countedWait() ;
381             }
382         }
383
384         if (etherealize_objects) {
385             Iterator JavaDoc iterator = null ;
386
387             // Make sure that poas cannot change while we copy it!
388
synchronized (pmi) {
389             if (debug) {
390                 ORBUtility.dprint( this,
391                 "run: Preparing to etherealize with pmi=" +
392                 pmi ) ;
393             }
394
395             iterator = (new HashSet JavaDoc(pmi.poas)).iterator();
396             }
397
398             while (iterator.hasNext()) {
399             // Each RETAIN+USE_SERVANT_MGR poa
400
// must call etherealize for all its objects
401
((POAImpl)iterator.next()).etherealizeAll();
402             }
403
404             synchronized (pmi) {
405             if (debug) {
406                 ORBUtility.dprint( this,
407                 "run: removing POAManager and clearing poas " +
408                 "with pmi=" + pmi ) ;
409             }
410
411             factory.removePoaManager(pmi);
412             poas.clear();
413             }
414         }
415         } finally {
416         if (debug) {
417             synchronized (pmi) {
418             ORBUtility.dprint( this, "Exiting run" ) ;
419             }
420         }
421         }
422     }
423     }
424
425     /**
426      * Added according to the spec CORBA V2.3; this returns the
427      * state of the POAManager
428      */

429
430     public org.omg.PortableServer.POAManagerPackage.State JavaDoc get_state () {
431     return state;
432     }
433
434 /****************************************************************************
435  * The following methods are used on the invocation path.
436  ****************************************************************************/

437
438     // called from POA.find_POA before calling
439
// AdapterActivator.unknown_adapter.
440
synchronized void checkIfActive()
441     {
442     try {
443         if (debug) {
444         ORBUtility.dprint( this,
445             "Calling checkIfActive for POAManagerImpl " + this ) ;
446         }
447
448         checkState();
449     } finally {
450         if (debug) {
451         ORBUtility.dprint( this,
452             "Exiting checkIfActive for POAManagerImpl " + this ) ;
453         }
454     }
455     }
456
457     private void checkState()
458     {
459     while ( state.value() != State._ACTIVE ) {
460         switch ( state.value() ) {
461         case State._HOLDING:
462             while ( state.value() == State._HOLDING ) {
463             countedWait() ;
464             }
465             break;
466
467         case State._DISCARDING:
468             throw factory.getWrapper().poaDiscarding() ;
469
470         case State._INACTIVE:
471             throw factory.getWrapper().poaInactive() ;
472         }
473     }
474     }
475
476     synchronized void enter()
477     {
478     try {
479         if (debug) {
480         ORBUtility.dprint( this,
481             "Calling enter for POAManagerImpl " + this ) ;
482         }
483
484         checkState();
485         nInvocations++;
486     } finally {
487         if (debug) {
488         ORBUtility.dprint( this,
489             "Exiting enter for POAManagerImpl " + this ) ;
490         }
491     }
492     }
493
494     synchronized void exit()
495     {
496     try {
497         if (debug) {
498         ORBUtility.dprint( this,
499             "Calling exit for POAManagerImpl " + this ) ;
500         }
501
502         nInvocations--;
503
504         if ( nInvocations == 0 ) {
505         // This notifies any threads that were in the
506
// wait_for_completion loop in hold/discard/deactivate().
507
notifyWaiters();
508         }
509     } finally {
510         if (debug) {
511         ORBUtility.dprint( this,
512             "Exiting exit for POAManagerImpl " + this ) ;
513         }
514     }
515     }
516
517     /** Activate the POAManager if no explicit state change has ever been
518      * previously invoked.
519      */

520     public synchronized void implicitActivation()
521     {
522     if (!explicitStateChange)
523         try {
524         activate() ;
525         } catch (org.omg.PortableServer.POAManagerPackage.AdapterInactive JavaDoc ai) {
526         // ignore the exception.
527
}
528     }
529 }
530
Popular Tags