public RequestToken startRequest()

in runtime/impl/src/main/java/com/google/apphosting/runtime/RequestManager.java [247:362]


  public RequestToken startRequest(
      AppVersion appVersion,
      AnyRpcServerContext rpc,
      RequestAPIData genericRequest,
      ResponseAPIData genericResponse,
      ThreadGroup requestThreadGroup) {
    long remainingTime = getAdjustedRpcDeadline(rpc, 60000);
    long softDeadlineMillis = Math.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(genericRequest)) {
      logger.atInfo().log("Received snapshot request");
      endAction = new DisableApiHostAction();
    } else {
      apiProxyImpl.enable();
      endAction = new NullAction();
    }

    TraceWriter traceWriter = TraceWriter.getTraceWriterForRequest(genericRequest, genericResponse);
    if (traceWriter != null) {
      URL requestURL = null;
      try {
        requestURL = new URL(genericRequest.getUrl());
      } catch (MalformedURLException e) {
        logger.atWarning().withCause(e).log(
            "Failed to extract path for trace due to malformed request URL: %s",
            genericRequest.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,
            genericRequest,
            genericResponse,
            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,
            genericResponse,
            requestId,
            genericRequest.getSecurityTicket(),
            timer,
            asyncFutures,
            appVersion,
            softDeadlineMillis,
            rpc,
            rpc.getStartTimeMillis(),
            traceWriter,
            state,
            endAction);

    requests.put(genericRequest.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;
  }