in runtime/lite/src/main/java/com/google/appengine/runtime/lite/RequestManager.java [191:307]
public RequestToken startRequest(
AppVersion appVersion,
AnyRpcServerContext rpc,
UPRequest upRequest,
MutableUpResponse upResponse,
ThreadGroup requestThreadGroup) {
long remainingTime = getAdjustedRpcDeadline(rpc, 60000);
long softDeadlineMillis = max(getAdjustedRpcDeadline(rpc, -1) - softDeadlineDelay, -1);
long millisUntilSoftDeadline = remainingTime - softDeadlineDelay;
Thread thread = Thread.currentThread();
// Hex-encode the request-id, formatted to 16 digits, in lower-case,
// with leading 0s, and no leading 0x to match the way stubby
// request ids are formatted in Google logs.
String requestId = String.format("%1$016x", rpc.getGlobalId());
logger.atInfo().log("Beginning request %s remaining millis : %d", requestId, remainingTime);
Runnable endAction;
if (isSnapshotRequest(upRequest)) {
logger.atInfo().log("Received snapshot request");
endAction = new DisableApiHostAction();
} else {
apiProxyImpl.enable();
endAction = new NullAction();
}
TraceWriter traceWriter = TraceWriter.getTraceWriterForRequest(upRequest, upResponse);
if (traceWriter != null) {
URL requestURL = null;
try {
requestURL = new URL(upRequest.getRequest().getUrl());
} catch (MalformedURLException e) {
logger.atWarning().withCause(e).log(
"Failed to extract path for trace due to malformed request URL: %s",
upRequest.getRequest().getUrl());
}
if (requestURL != null) {
traceWriter.startRequestSpan(requestURL.getPath());
} else {
traceWriter.startRequestSpan("Unparsable URL");
}
}
CpuRatioTimer timer = timerFactory.getCpuRatioTimer(thread);
// This list is used to block the end of a request until all API
// calls have completed or timed out.
List<Future<?>> asyncFutures = Collections.synchronizedList(new ArrayList<Future<?>>());
// This semaphore maintains the count of currently running API
// calls so we can block future calls if too many calls are
// outstanding.
Semaphore outstandingApiRpcSemaphore = new Semaphore(maxOutstandingApiRpcs);
RequestState state = new RequestState();
state.recordRequestThread(Thread.currentThread());
ApiProxy.Environment environment =
apiProxyImpl.createEnvironment(
appVersion,
upRequest,
upResponse,
traceWriter,
timer,
requestId,
asyncFutures,
outstandingApiRpcSemaphore,
requestThreadGroup,
state,
millisUntilSoftDeadline);
// If the instance id was not set (e.g. for some Titanium runtimes), set the instance id
// retrieved from the environment variable.
String instanceId = environmentVariables.get("GAE_INSTANCE");
if (!Strings.isNullOrEmpty(instanceId)) {
environment.getAttributes().putIfAbsent(INSTANCE_ID_ENV_ATTRIBUTE, instanceId);
}
// Create a RequestToken where we will store any state we will
// need to restore in finishRequest().
RequestToken token =
new RequestToken(
thread,
upResponse,
requestId,
upRequest.getSecurityTicket(),
timer,
asyncFutures,
appVersion,
softDeadlineMillis,
rpc,
rpc.getStartTimeMillis(),
traceWriter,
state,
endAction);
requests.put(upRequest.getSecurityTicket(), token);
// Tell the ApiProxy about our current request environment so that
// it can make callbacks and pass along information about the
// logged-in user.
ApiProxy.setEnvironmentForCurrentThread(environment);
// Start counting CPU cycles used by this thread.
timer.start();
if (!disableDeadlineTimers) {
// The timing conventions here are a bit wonky, but this is what
// the Python runtime does.
logger.atInfo().log(
"Scheduling soft deadline in %d ms for %s", millisUntilSoftDeadline, requestId);
token.addScheduledFuture(
schedule(new DeadlineRunnable(this, token, false), millisUntilSoftDeadline));
}
return token;
}