AOMEntry.java revision 608:7e06bf1dcb09
1/* 2 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 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 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.corba.se.impl.oa.poa ; 27 28import org.omg.CORBA.INTERNAL ; 29 30import com.sun.corba.se.spi.orb.ORB ; 31 32import com.sun.corba.se.spi.orbutil.fsm.Action ; 33import com.sun.corba.se.spi.orbutil.fsm.ActionBase ; 34import com.sun.corba.se.spi.orbutil.fsm.Guard ; 35import com.sun.corba.se.spi.orbutil.fsm.GuardBase ; 36import com.sun.corba.se.spi.orbutil.fsm.State ; 37import com.sun.corba.se.spi.orbutil.fsm.StateImpl ; 38import com.sun.corba.se.spi.orbutil.fsm.Input ; 39import com.sun.corba.se.spi.orbutil.fsm.InputImpl ; 40import com.sun.corba.se.spi.orbutil.fsm.FSM ; 41import com.sun.corba.se.spi.orbutil.fsm.FSMImpl ; 42import com.sun.corba.se.spi.orbutil.fsm.StateEngine ; 43import com.sun.corba.se.spi.orbutil.fsm.StateEngineFactory ; 44 45import com.sun.corba.se.impl.orbutil.concurrent.Mutex ; 46import com.sun.corba.se.impl.orbutil.concurrent.CondVar ; 47 48import org.omg.CORBA.SystemException ; 49 50import org.omg.PortableServer.POAPackage.ObjectAlreadyActive ; 51 52/** AOMEntry represents a Servant or potential Servant in the ActiveObjectMap. 53* It may be in several states to allow for long incarnate or etherealize operations. 54* The methods on this class mostly represent input symbols to the state machine 55* that controls the lifecycle of the entry. A library is used to build the state 56* machine rather than the more usual state pattern so that the state machine 57* transitions are explicitly visible. 58*/ 59public class AOMEntry extends FSMImpl { 60 private final Thread[] etherealizer ; // The actual etherealize operation 61 // for this entry. It is 62 // represented as a Thread because 63 // the POA.deactivate_object never 64 // waits for the completion. 65 private final int[] counter ; // single element holder for counter 66 // accessed in actions 67 private final CondVar wait ; // accessed in actions 68 69 final POAImpl poa ; 70 71 public static final State INVALID = new StateImpl( "Invalid" ) ; 72 public static final State INCARN = new StateImpl( "Incarnating" ) { 73 public void postAction( FSM fsm ) { 74 AOMEntry entry = (AOMEntry)fsm ; 75 entry.wait.broadcast() ; 76 } 77 }; 78 public static final State VALID = new StateImpl( "Valid" ) ; 79 public static final State ETHP = new StateImpl( "EtherealizePending" ) ; 80 public static final State ETH = new StateImpl( "Etherealizing" ) { 81 public void preAction( FSM fsm ) { 82 AOMEntry entry = (AOMEntry)fsm ; 83 Thread etherealizer = entry.etherealizer[0] ; 84 if (etherealizer != null) 85 etherealizer.start() ; 86 } 87 88 public void postAction( FSM fsm ) { 89 AOMEntry entry = (AOMEntry)fsm ; 90 entry.wait.broadcast() ; 91 } 92 }; 93 public static final State DESTROYED = new StateImpl( "Destroyed" ) ; 94 95 static final Input START_ETH = new InputImpl( "startEtherealize" ) ; 96 static final Input ETH_DONE = new InputImpl( "etherealizeDone" ) ; 97 static final Input INC_DONE = new InputImpl( "incarnateDone" ) ; 98 static final Input INC_FAIL = new InputImpl( "incarnateFailure" ) ; 99 static final Input ACTIVATE = new InputImpl( "activateObject" ) ; 100 static final Input ENTER = new InputImpl( "enter" ) ; 101 static final Input EXIT = new InputImpl( "exit" ) ; 102 103 private static Action incrementAction = new ActionBase( "increment" ) { 104 public void doIt( FSM fsm, Input in ) { 105 AOMEntry entry = (AOMEntry)fsm ; 106 entry.counter[0]++ ; 107 } 108 } ; 109 110 private static Action decrementAction = new ActionBase( "decrement" ) { 111 public void doIt( FSM fsm, Input in ) { 112 AOMEntry entry = (AOMEntry)fsm ; 113 if (entry.counter[0] > 0) 114 entry.counter[0]-- ; 115 else 116 throw entry.poa.lifecycleWrapper().aomEntryDecZero() ; 117 } 118 } ; 119 120 private static Action throwIllegalStateExceptionAction = new ActionBase( 121 "throwIllegalStateException" ) { 122 public void doIt( FSM fsm, Input in ) { 123 throw new IllegalStateException( 124 "No transitions allowed from the DESTROYED state" ) ; 125 } 126 } ; 127 128 private static Action oaaAction = new ActionBase( "throwObjectAlreadyActive" ) { 129 public void doIt( FSM fsm, Input in ) { 130 throw new RuntimeException( new ObjectAlreadyActive() ) ; 131 } 132 } ; 133 134 private static Guard waitGuard = new GuardBase( "wait" ) { 135 public Guard.Result evaluate( FSM fsm, Input in ) { 136 AOMEntry entry = (AOMEntry)fsm ; 137 try { 138 entry.wait.await() ; 139 } catch (InterruptedException exc) { 140 // XXX Log this 141 // NO-OP 142 } 143 144 return Guard.Result.DEFERED ; 145 } 146 } ; 147 148 149 private static class CounterGuard extends GuardBase { 150 private int value ; 151 152 public CounterGuard( int value ) 153 { 154 super( "counter>" + value ) ; 155 this.value = value ; 156 } 157 158 public Guard.Result evaluate( FSM fsm, Input in ) 159 { 160 AOMEntry entry = (AOMEntry)fsm ; 161 return Guard.Result.convert( entry.counter[0] > value ) ; 162 } 163 } ; 164 165 private static GuardBase greaterZeroGuard = new CounterGuard( 0 ) ; 166 private static Guard zeroGuard = new Guard.Complement( greaterZeroGuard ) ; 167 private static GuardBase greaterOneGuard = new CounterGuard( 1 ) ; 168 private static Guard oneGuard = new Guard.Complement( greaterOneGuard ) ; 169 170 private static StateEngine engine ; 171 172 static { 173 engine = StateEngineFactory.create() ; 174 175 // State, Input, Guard, Action, new State 176 177 engine.add( INVALID, ENTER, incrementAction, INCARN ) ; 178 engine.add( INVALID, ACTIVATE, null, VALID ) ; 179 engine.setDefault( INVALID ) ; 180 181 engine.add( INCARN, ENTER, waitGuard, null, INCARN ) ; 182 engine.add( INCARN, EXIT, null, INCARN ) ; 183 engine.add( INCARN, START_ETH, waitGuard, null, INCARN ) ; 184 engine.add( INCARN, INC_DONE, null, VALID ) ; 185 engine.add( INCARN, INC_FAIL, decrementAction, INVALID ) ; 186 engine.add( INCARN, ACTIVATE, oaaAction, INCARN ) ; 187 188 engine.add( VALID, ENTER, incrementAction, VALID ) ; 189 engine.add( VALID, EXIT, decrementAction, VALID ) ; 190 engine.add( VALID, START_ETH, greaterZeroGuard, null, ETHP ) ; 191 engine.add( VALID, START_ETH, zeroGuard, null, ETH ) ; 192 engine.add( VALID, ACTIVATE, oaaAction, VALID ) ; 193 194 engine.add( ETHP, ENTER, waitGuard, null, ETHP ) ; 195 engine.add( ETHP, START_ETH, null, ETHP ) ; 196 engine.add( ETHP, EXIT, greaterOneGuard, decrementAction, ETHP ) ; 197 engine.add( ETHP, EXIT, oneGuard, decrementAction, ETH ) ; 198 engine.add( ETHP, ACTIVATE, oaaAction, ETHP ) ; 199 200 engine.add( ETH, START_ETH, null, ETH ) ; 201 engine.add( ETH, ETH_DONE, null, DESTROYED ) ; 202 engine.add( ETH, ACTIVATE, oaaAction, ETH ) ; 203 engine.add( ETH, ENTER, waitGuard, null, ETH ) ; 204 205 engine.setDefault( DESTROYED, throwIllegalStateExceptionAction, DESTROYED ) ; 206 207 engine.done() ; 208 } 209 210 public AOMEntry( POAImpl poa ) 211 { 212 super( engine, INVALID, ((ORB)poa.getORB()).poaFSMDebugFlag ) ; 213 this.poa = poa ; 214 etherealizer = new Thread[1] ; 215 etherealizer[0] = null ; 216 counter = new int[1] ; 217 counter[0] = 0 ; 218 wait = new CondVar( poa.poaMutex, 219 ((ORB)poa.getORB()).poaConcurrencyDebugFlag ) ; 220 } 221 222 // Methods that drive the FSM: the real interface to this class 223 // Most just call the doIt method, but startEtherealize needs 224 // the etherealizer. 225 public void startEtherealize( Thread etherealizer ) 226 { 227 this.etherealizer[0] = etherealizer ; 228 doIt( START_ETH ) ; 229 } 230 231 public void etherealizeComplete() { doIt( ETH_DONE ) ; } 232 public void incarnateComplete() { doIt( INC_DONE ) ; } 233 public void incarnateFailure() { doIt( INC_FAIL ) ; } 234 public void activateObject() throws ObjectAlreadyActive { 235 try { 236 doIt( ACTIVATE ) ; 237 } catch (RuntimeException exc) { 238 Throwable thr = exc.getCause() ; 239 if (thr instanceof ObjectAlreadyActive) 240 throw (ObjectAlreadyActive)thr ; 241 else 242 throw exc ; 243 } 244 } 245 public void enter() { doIt( ENTER ) ; } 246 public void exit() { doIt( EXIT ) ; } 247} 248