1 package com
.google
.appengine
.tools
.development
;
3 import com
.google
.appengine
.tools
.development
.ApplicationConfigurationManager
.ServerConfigurationHandle
;
4 import com
.google
.appengine
.tools
.development
.InstanceStateHolder
.InstanceState
;
7 import java
.security
.AccessController
;
8 import java
.security
.PrivilegedExceptionAction
;
10 import java
.util
.concurrent
.CountDownLatch
;
11 import java
.util
.concurrent
.TimeUnit
;
12 import java
.util
.logging
.Logger
;
15 * {@link InstanceHolder} for a {@link ManualServer}.
17 class ManualServerInstanceHolder
extends AbstractServerInstanceHolder
{
18 private static final int MAX_START_QUEUE_TIME_MS
= 30 * 1000;
19 private static final Logger LOGGER
= Logger
.getLogger(ManualServerInstanceHolder
.class.getName());
21 private final String serverName
;
22 private final InstanceStateHolder stateHolder
;
23 private final InstanceHelper instanceHelper
;
24 private volatile CountDownLatch startRequestLatch
;
26 private ServerConfigurationHandle serverConfigurationHandle
;
27 private String serverInfo
;
28 private File externalResourceDir
;
29 private String address
;
30 private Map
<String
, Object
> containerConfigProperties
;
31 private DevAppServerImpl devAppServer
;
36 * Construct an instance holder.
37 * @param serverName the server's name or 'default'
38 * @param containerService for the instance.
39 * @param instance nonnegative instance number or
40 * {link {@link LocalEnvironment#MAIN_INSTANCE}.
41 * @param stateHolder holder for the instance state.
42 * @param instanceHelper helper for operating on the instance.
44 ManualServerInstanceHolder(String serverName
, ContainerService containerService
, int instance
,
45 InstanceStateHolder stateHolder
, InstanceHelper instanceHelper
) {
46 super(containerService
, instance
);
47 this.serverName
= serverName
;
48 this.stateHolder
= stateHolder
;
49 this.instanceHelper
= instanceHelper
;
50 this.startRequestLatch
= new CountDownLatch(1);
54 public boolean isServerLoadBalancingServer() {
55 return isMainInstance();
59 public boolean expectsGeneratedStartRequest() {
60 return !isMainInstance();
64 public String
toString() {
65 return "ManualServerInstanceHolder: containerservice=" + getContainerService() + " instance="
70 public void startUp() throws Exception
{
71 stateHolder
.testAndSet(InstanceState
.INITIALIZING
, InstanceState
.SHUTDOWN
);
72 getContainerService().startup();
73 stateHolder
.testAndSet(InstanceState
.STOPPED
, InstanceState
.INITIALIZING
);
78 public void createConnection() throws Exception
{
79 super.createConnection();
80 if (port
!= null && port
.intValue() != getContainerService().getPort()) {
81 throw new IllegalStateException("Port has been reassigned for"
82 + " server=" + serverName
83 + " instance=" + getInstance()
84 + " original port = " + port
85 + " new port=" + getContainerService().getPort());
87 this.port
= getContainerService().getPort();
90 void setConfiguration(ServerConfigurationHandle serverConfigurationHandle
,
91 String serverInfo
, File externalResourceDir
, String address
,
92 Map
<String
, Object
> containerConfigProperties
, DevAppServerImpl devAppServer
) {
93 this.serverConfigurationHandle
= serverConfigurationHandle
;
94 this.serverInfo
= serverInfo
;
95 this.externalResourceDir
= externalResourceDir
;
96 this.address
= address
;
97 this.containerConfigProperties
= containerConfigProperties
;
98 this.devAppServer
= devAppServer
;
101 LocalServerEnvironment
doConfigure() {
102 ContainerService containerService
= getContainerService();
103 LocalServerEnvironment result
= containerService
.configure(serverInfo
, address
,
104 getPortForDoConfigure(), serverConfigurationHandle
, externalResourceDir
,
105 containerConfigProperties
, getInstance(), devAppServer
);
110 * Returns the port to pass to doConfigure.
112 * The port is chosen as follows
114 * <li> If a port is already assigned we use it. This indicates we are
115 * re starting the instance.
116 * <li> Otherwise if the user specified port using service properties we use that.
117 * <li> Otherwise we use the value 0 which causes the container service to
122 private int getPortForDoConfigure() {
124 return DevAppServerPortPropertyHelper
.getPort(serverName
,
125 getInstance(), devAppServer
.getServiceProperties());
131 void stopServing() throws Exception
{
132 if (isMainInstance()) {
133 stateHolder
.testAndSet(InstanceState
.STOPPED
, InstanceState
.RUNNING
);
135 instanceHelper
.shutdown();
136 stateHolder
.testAndSet(InstanceState
.INITIALIZING
, InstanceState
.SHUTDOWN
);
137 startRequestLatch
= new CountDownLatch(1);
140 AccessController
.doPrivileged(new PrivilegedExceptionAction
<Object
>() {
142 public Object
run() throws Exception
{
143 getContainerService().startup();
147 stateHolder
.testAndSet(InstanceState
.STOPPED
, InstanceState
.INITIALIZING
);
151 void startServing() throws Exception
{
152 if (!stateHolder
.test(InstanceState
.STOPPED
)) {
153 throw new IllegalStateException("stopServer state=" + stateHolder
+ " server=" + serverName
);
155 if (isMainInstance()) {
156 stateHolder
.testAndSet(InstanceState
.RUNNING
, InstanceState
.STOPPED
);
158 stateHolder
.testAndSet(InstanceState
.SLEEPING
, InstanceState
.STOPPED
);
163 void requireState(String operation
, InstanceState requiredState
) {
164 stateHolder
.requireState(operation
, requiredState
);
167 private void sendStartRequest() {
168 instanceHelper
.sendStartRequest(new Runnable() {
172 startRequestLatch
.countDown();
178 public boolean acquireServingPermit() {
179 LOGGER
.finest(String
.format("trying to get serving permit for server %d.%s", getInstance(),
182 synchronized (stateHolder
) {
183 if (!stateHolder
.acceptsConnections()) {
184 LOGGER
.finest(serverName
+ ": got request but server is not in a serving state");
188 if (stateHolder
.test(InstanceState
.SLEEPING
)) {
189 LOGGER
.finest(serverName
+ ": waking up sleeping server");
193 if (stateHolder
.test(InstanceState
.RUNNING_START_REQUEST
)) {
194 maxWaitTime
= MAX_START_QUEUE_TIME_MS
;
198 boolean gotPermit
= startRequestLatch
.await(maxWaitTime
, TimeUnit
.MILLISECONDS
);
199 LOGGER
.finest(getInstance() + "." + serverName
+ ": tried to get server permit, timeout="
200 + maxWaitTime
+ " success=" + gotPermit
);
202 } catch (InterruptedException e
) {
204 getInstance() + "." + serverName
+ ": got interrupted while waiting for serving permit");
210 public boolean isStopped() {
211 return stateHolder
.test(InstanceState
.STOPPED
);