1 /* |
1 /* |
2 * Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved. |
2 * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Sun designates this |
7 * published by the Free Software Foundation. Sun designates this |
183 private Vector dynamicRequests ; |
183 private Vector dynamicRequests ; |
184 private SynchVariable svResponseReceived ; |
184 private SynchVariable svResponseReceived ; |
185 |
185 |
186 private java.lang.Object runObj = new java.lang.Object(); |
186 private java.lang.Object runObj = new java.lang.Object(); |
187 private java.lang.Object shutdownObj = new java.lang.Object(); |
187 private java.lang.Object shutdownObj = new java.lang.Object(); |
188 private java.lang.Object waitForCompletionObj = new java.lang.Object(); |
|
189 private static final byte STATUS_OPERATING = 1; |
188 private static final byte STATUS_OPERATING = 1; |
190 private static final byte STATUS_SHUTTING_DOWN = 2; |
189 private static final byte STATUS_SHUTTING_DOWN = 2; |
191 private static final byte STATUS_SHUTDOWN = 3; |
190 private static final byte STATUS_SHUTDOWN = 3; |
192 private static final byte STATUS_DESTROYED = 4; |
191 private static final byte STATUS_DESTROYED = 4; |
193 private byte status = STATUS_OPERATING; |
192 private byte status = STATUS_OPERATING; |
194 |
193 |
195 // XXX Should we move invocation tracking to the first level server dispatcher? |
194 // XXX Should we move invocation tracking to the first level server dispatcher? |
196 private java.lang.Object invocationObj = new java.lang.Object(); |
195 private java.lang.Object invocationObj = new java.lang.Object(); |
197 private int numInvocations = 0; |
|
198 |
196 |
199 // thread local variable to store a boolean to detect deadlock in |
197 // thread local variable to store a boolean to detect deadlock in |
200 // ORB.shutdown(true). |
198 // ORB.shutdown(true). |
201 private ThreadLocal isProcessingInvocation = new ThreadLocal () { |
199 private ThreadLocal isProcessingInvocation = new ThreadLocal () { |
202 protected java.lang.Object initialValue() { |
200 protected java.lang.Object initialValue() { |
1243 } |
1241 } |
1244 } |
1242 } |
1245 |
1243 |
1246 public void shutdown(boolean wait_for_completion) |
1244 public void shutdown(boolean wait_for_completion) |
1247 { |
1245 { |
|
1246 // to wait for completion, we would deadlock, so throw a standard |
|
1247 // OMG exception. |
|
1248 if (wait_for_completion && ((Boolean)isProcessingInvocation.get()).booleanValue()) { |
|
1249 throw omgWrapper.shutdownWaitForCompletionDeadlock() ; |
|
1250 } |
|
1251 |
|
1252 boolean doShutdown = false ; |
|
1253 |
1248 synchronized (this) { |
1254 synchronized (this) { |
1249 checkShutdownState(); |
1255 checkShutdownState() ; |
1250 } |
1256 |
1251 |
1257 if (status == STATUS_SHUTTING_DOWN) { |
1252 // Avoid more than one thread performing shutdown at a time. |
1258 if (!wait_for_completion) |
|
1259 // If we are already shutting down and don't want |
|
1260 // to wait, nothing to do: return. |
|
1261 return ; |
|
1262 } else { |
|
1263 // The ORB status was STATUS_OPERATING, so start the shutdown. |
|
1264 status = STATUS_SHUTTING_DOWN ; |
|
1265 doShutdown = true ; |
|
1266 } |
|
1267 } |
|
1268 |
|
1269 // At this point, status is SHUTTING_DOWN. |
|
1270 // All shutdown calls with wait_for_completion == true must synchronize |
|
1271 // here. Only the first call will be made with doShutdown == true. |
1253 synchronized (shutdownObj) { |
1272 synchronized (shutdownObj) { |
1254 checkShutdownState(); |
1273 if (doShutdown) { |
1255 // This is to avoid deadlock |
1274 // shutdownServants will set all POAManagers into the |
1256 if (wait_for_completion && |
1275 // INACTIVE state, causing request to be rejected. |
1257 isProcessingInvocation.get() == Boolean.TRUE) { |
1276 // If wait_for_completion is true, this will not return until |
1258 throw omgWrapper.shutdownWaitForCompletionDeadlock() ; |
1277 // all invocations have completed. |
1259 } |
1278 shutdownServants(wait_for_completion); |
1260 |
1279 |
1261 status = STATUS_SHUTTING_DOWN; |
1280 synchronized (runObj) { |
1262 // XXX access to requestDispatcherRegistry should be protected |
1281 runObj.notifyAll(); |
1263 // by the ORBImpl instance monitor, but is not here in the |
1282 } |
1264 // shutdownServants call. |
1283 |
1265 shutdownServants(wait_for_completion); |
1284 synchronized (this) { |
1266 if (wait_for_completion) { |
1285 status = STATUS_SHUTDOWN; |
1267 synchronized ( waitForCompletionObj ) { |
|
1268 while (numInvocations > 0) { |
|
1269 try { |
|
1270 waitForCompletionObj.wait(); |
|
1271 } catch (InterruptedException ex) {} |
|
1272 } |
|
1273 } |
1286 } |
1274 } |
1287 } |
1275 synchronized ( runObj ) { |
|
1276 runObj.notifyAll(); |
|
1277 } |
|
1278 status = STATUS_SHUTDOWN; |
|
1279 } |
1288 } |
1280 } |
1289 } |
1281 |
1290 |
1282 /** This method shuts down the ORB and causes orb.run() to return. |
1291 /** This method shuts down the ORB and causes orb.run() to return. |
1283 * It will cause all POAManagers to be deactivated, which in turn |
1292 * It will cause all POAManagers to be deactivated, which in turn |
1312 |
1321 |
1313 public void startingDispatch() |
1322 public void startingDispatch() |
1314 { |
1323 { |
1315 synchronized (invocationObj) { |
1324 synchronized (invocationObj) { |
1316 isProcessingInvocation.set(Boolean.TRUE); |
1325 isProcessingInvocation.set(Boolean.TRUE); |
1317 numInvocations++; |
|
1318 } |
1326 } |
1319 } |
1327 } |
1320 |
1328 |
1321 public void finishedDispatch() |
1329 public void finishedDispatch() |
1322 { |
1330 { |
1323 synchronized (invocationObj) { |
1331 synchronized (invocationObj) { |
1324 numInvocations--; |
|
1325 isProcessingInvocation.set(Boolean.FALSE); |
1332 isProcessingInvocation.set(Boolean.FALSE); |
1326 if (numInvocations == 0) { |
|
1327 synchronized (waitForCompletionObj) { |
|
1328 waitForCompletionObj.notifyAll(); |
|
1329 } |
|
1330 } else if (numInvocations < 0) { |
|
1331 throw wrapper.numInvocationsAlreadyZero( |
|
1332 CompletionStatus.COMPLETED_YES ) ; |
|
1333 } |
|
1334 } |
1333 } |
1335 } |
1334 } |
1336 |
1335 |
1337 /** |
1336 /** |
1338 * formal/99-10-07 p 159: "If destroy is called on an ORB that has |
1337 * formal/99-10-07 p 159: "If destroy is called on an ORB that has |
1339 * not been shut down, it will start the shutdown process and block until |
1338 * not been shut down, it will start the shutdown process and block until |
1340 * the ORB has shut down before it destroys the ORB." |
1339 * the ORB has shut down before it destroys the ORB." |
1341 */ |
1340 */ |
1342 public synchronized void destroy() |
1341 public synchronized void destroy() |
1343 { |
1342 { |
1344 if (status == STATUS_OPERATING) { |
1343 boolean shutdownFirst = false ; |
|
1344 |
|
1345 synchronized (this) { |
|
1346 shutdownFirst = (status == STATUS_OPERATING) ; |
|
1347 } |
|
1348 |
|
1349 if (shutdownFirst) { |
1345 shutdown(true); |
1350 shutdown(true); |
1346 } |
1351 } |
1347 getCorbaTransportManager().close(); |
1352 |
1348 getPIHandler().destroyInterceptors() ; |
1353 synchronized (this) { |
1349 status = STATUS_DESTROYED; |
1354 if (status < STATUS_DESTROYED) { |
|
1355 getCorbaTransportManager().close(); |
|
1356 getPIHandler().destroyInterceptors() ; |
|
1357 status = STATUS_DESTROYED; |
|
1358 } |
|
1359 } |
|
1360 |
1350 } |
1361 } |
1351 |
1362 |
1352 /** |
1363 /** |
1353 * Registers a value factory for a particular repository ID. |
1364 * Registers a value factory for a particular repository ID. |
1354 * |
1365 * |