Add runtime package.

Change-Id: I243548c0e018093d262b0a7d730970bc220c6072
diff --git a/README.md b/README.md
index d1f141b..d01f7d5 100644
--- a/README.md
+++ b/README.md
@@ -66,7 +66,7 @@
 * `aetest` no longer declares its own Context type, and uses the standard one instead.
 * `taskqueue.QueueStats` no longer takes a maxTasks argument. That argument has been
   deprecated and unused for a long time.
-* `appengine/cloudsql` and `appengine/runtime` have not been ported yet.
+* `appengine/cloudsql` has not been ported yet.
 * `appengine.BackendHostname` and `appengine.BackendInstance` were for the deprecated backends feature.
   Use `appengine.ModuleHostname`and `appengine.ModuleName` instead.
 * `appengine.IsCapabilityDisabled` and `appengine/capability` are obsolete.
diff --git a/runtime/runtime.go b/runtime/runtime.go
new file mode 100644
index 0000000..ece9765
--- /dev/null
+++ b/runtime/runtime.go
@@ -0,0 +1,148 @@
+// Copyright 2011 Google Inc. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+/*
+Package runtime exposes information about the resource usage of the application.
+It also provides a way to run code in a new background context of a module.
+
+This package does not work on Managed VMs.
+*/
+package runtime // import "google.golang.org/appengine/runtime"
+
+import (
+	"net/http"
+
+	"golang.org/x/net/context"
+
+	"google.golang.org/appengine"
+	"google.golang.org/appengine/internal"
+	pb "google.golang.org/appengine/internal/system"
+)
+
+// Statistics represents the system's statistics.
+type Statistics struct {
+	// CPU records the CPU consumed by this instance, in megacycles.
+	CPU struct {
+		Total   float64
+		Rate1M  float64 // consumption rate over one minute
+		Rate10M float64 // consumption rate over ten minutes
+	}
+	// RAM records the memory used by the instance, in megabytes.
+	RAM struct {
+		Current    float64
+		Average1M  float64 // average usage over one minute
+		Average10M float64 // average usage over ten minutes
+	}
+}
+
+func Stats(c context.Context) (*Statistics, error) {
+	req := &pb.GetSystemStatsRequest{}
+	res := &pb.GetSystemStatsResponse{}
+	if err := internal.Call(c, "system", "GetSystemStats", req, res); err != nil {
+		return nil, err
+	}
+	s := &Statistics{}
+	if res.Cpu != nil {
+		s.CPU.Total = res.Cpu.GetTotal()
+		s.CPU.Rate1M = res.Cpu.GetRate1M()
+		s.CPU.Rate10M = res.Cpu.GetRate10M()
+	}
+	if res.Memory != nil {
+		s.RAM.Current = res.Memory.GetCurrent()
+		s.RAM.Average1M = res.Memory.GetAverage1M()
+		s.RAM.Average10M = res.Memory.GetAverage10M()
+	}
+	return s, nil
+}
+
+/*
+RunInBackground makes an API call that triggers an /_ah/background request.
+
+There are two independent code paths that need to make contact:
+the RunInBackground code, and the /_ah/background handler. The matchmaker
+loop arranges for the two paths to meet. The RunInBackground code passes
+a send to the matchmaker, the /_ah/background passes a recv to the matchmaker,
+and the matchmaker hooks them up.
+*/
+
+func init() {
+	http.HandleFunc("/_ah/background", handleBackground)
+
+	sc := make(chan send)
+	rc := make(chan recv)
+	sendc, recvc = sc, rc
+	go matchmaker(sc, rc)
+}
+
+var (
+	sendc chan<- send // RunInBackground sends to this
+	recvc chan<- recv // handleBackground sends to this
+)
+
+type send struct {
+	id string
+	f  func(context.Context)
+}
+
+type recv struct {
+	id string
+	ch chan<- func(context.Context)
+}
+
+func matchmaker(sendc <-chan send, recvc <-chan recv) {
+	// When one side of the match arrives before the other
+	// it is inserted in the corresponding map.
+	waitSend := make(map[string]send)
+	waitRecv := make(map[string]recv)
+
+	for {
+		select {
+		case s := <-sendc:
+			if r, ok := waitRecv[s.id]; ok {
+				// meet!
+				delete(waitRecv, s.id)
+				r.ch <- s.f
+			} else {
+				// waiting for r
+				waitSend[s.id] = s
+			}
+		case r := <-recvc:
+			if s, ok := waitSend[r.id]; ok {
+				// meet!
+				delete(waitSend, r.id)
+				r.ch <- s.f
+			} else {
+				// waiting for s
+				waitRecv[r.id] = r
+			}
+		}
+	}
+}
+
+var newContext = appengine.NewContext // for testing
+
+func handleBackground(w http.ResponseWriter, req *http.Request) {
+	id := req.Header.Get("X-AppEngine-BackgroundRequest")
+
+	ch := make(chan func(context.Context))
+	recvc <- recv{id, ch}
+	(<-ch)(newContext(req))
+}
+
+// RunInBackground runs f in a background goroutine in this process.
+// f is provided a context that may outlast the context provided to RunInBackground.
+// This is only valid to invoke from a manually scaled module.
+func RunInBackground(c context.Context, f func(c context.Context)) error {
+	req := &pb.StartBackgroundRequestRequest{}
+	res := &pb.StartBackgroundRequestResponse{}
+	if err := internal.Call(c, "system", "StartBackgroundRequest", req, res); err != nil {
+		return err
+	}
+	sendc <- send{res.GetRequestId(), f}
+	return nil
+}
+
+func init() {
+	internal.RegisterErrorCodeMap("system", pb.SystemServiceError_ErrorCode_name)
+}
diff --git a/runtime/runtime_test.go b/runtime/runtime_test.go
new file mode 100644
index 0000000..8f3a124
--- /dev/null
+++ b/runtime/runtime_test.go
@@ -0,0 +1,101 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import (
+	"fmt"
+	"net/http"
+	"net/http/httptest"
+	"testing"
+	"time"
+
+	"github.com/golang/protobuf/proto"
+	"golang.org/x/net/context"
+
+	"google.golang.org/appengine/internal/aetesting"
+	pb "google.golang.org/appengine/internal/system"
+)
+
+func TestRunInBackgroundSendFirst(t *testing.T) { testRunInBackground(t, true) }
+func TestRunInBackgroundRecvFirst(t *testing.T) { testRunInBackground(t, false) }
+
+func testRunInBackground(t *testing.T, sendFirst bool) {
+	srv := httptest.NewServer(nil)
+	defer srv.Close()
+
+	const id = "f00bar"
+	sendWait, recvWait := make(chan bool), make(chan bool)
+	sbr := make(chan bool) // strobed when system.StartBackgroundRequest has started
+
+	calls := 0
+	c := aetesting.FakeSingleContext(t, "system", "StartBackgroundRequest", func(req *pb.StartBackgroundRequestRequest, res *pb.StartBackgroundRequestResponse) error {
+		calls++
+		if calls > 1 {
+			t.Errorf("Too many calls to system.StartBackgroundRequest")
+		}
+		sbr <- true
+		res.RequestId = proto.String(id)
+		<-sendWait
+		return nil
+	})
+
+	var c2 context.Context // a fake
+	newContext = func(*http.Request) context.Context {
+		return c2
+	}
+
+	var fRun int
+	f := func(c3 context.Context) {
+		fRun++
+		if c3 != c2 {
+			t.Errorf("f got a different context than expected")
+		}
+	}
+
+	ribErrc := make(chan error)
+	go func() {
+		ribErrc <- RunInBackground(c, f)
+	}()
+
+	brErrc := make(chan error)
+	go func() {
+		<-sbr
+		req, err := http.NewRequest("GET", srv.URL+"/_ah/background", nil)
+		if err != nil {
+			brErrc <- fmt.Errorf("http.NewRequest: %v", err)
+			return
+		}
+		req.Header.Set("X-AppEngine-BackgroundRequest", id)
+		client := &http.Client{
+			Transport: &http.Transport{
+				Proxy: http.ProxyFromEnvironment,
+			},
+		}
+
+		<-recvWait
+		_, err = client.Do(req)
+		brErrc <- err
+	}()
+
+	// Send and receive are both waiting at this point.
+	waits := [2]chan bool{sendWait, recvWait}
+	if !sendFirst {
+		waits[0], waits[1] = waits[1], waits[0]
+	}
+	waits[0] <- true
+	time.Sleep(100 * time.Millisecond)
+	waits[1] <- true
+
+	if err := <-ribErrc; err != nil {
+		t.Fatalf("RunInBackground: %v", err)
+	}
+	if err := <-brErrc; err != nil {
+		t.Fatalf("background request: %v", err)
+	}
+
+	if fRun != 1 {
+		t.Errorf("Got %d runs of f, want 1", fRun)
+	}
+}