java: Switch to the new init/login scheme

The new scheme works like this:

 - init() function is synchronous, it takes the configuration
   parameters and, if isLoggedIn() is true then it starts Syncbase. It
   expects that the database, userdata syncgroup, etc. to already
   exist.

 - isLoggedIn() function is synchronous and it requires init() to have
   been called.

 - login() function is asynchronous, does the oauth token to blessing
   exchange, it requires init() to have been called, starts the
   Syncbase and creates the expected default state (create the default
   database, userdata syncgroup, etc).

 - database() function is synchronous, requires that isLoggedIn() is
   true and returns a Database object right away.

This change only partially implements the above plan (the login is not
wired yet).

The C API gets two new functions:

  - v23_syncbase_Serve(cErr *C.v23_syncbase_VError)
  - v23_syncbase_IsLoggedIn(cIsLoggedIn *C.v23_syncbase_Bool)

The Java high-level API doesn't have the inner DatabaseCallback and
have instead an inner LoginCallback.

This change also switches the tests for core/ and internal/ to
init/shutdown a single time. These makes the tests much faster.

MultiPart: 1/2
Change-Id: Ib6411ec9c2e7b9fe1f7dd8f22880012425396515
diff --git a/services/syncbase/bridge/bridge.go b/services/syncbase/bridge/bridge.go
index 3abed4d..d20f71c 100644
--- a/services/syncbase/bridge/bridge.go
+++ b/services/syncbase/bridge/bridge.go
@@ -18,31 +18,26 @@
 // Bridge object, representing an in-process Syncbase singleton.
 type Bridge struct {
 	Ctx      *context.T
-	Shutdown context.CancelFunc
-	srv      rpc.Server
-	disp     rpc.Dispatcher
+	Shutdown v23.Shutdown
+	Srv      rpc.Server
+	Disp     rpc.Dispatcher
 	Cleanup  func()
 }
 
-func NewBridge(ctx *context.T, shutdown context.CancelFunc, srv rpc.Server, disp rpc.Dispatcher, cleanup func()) *Bridge {
-	return &Bridge{Ctx: ctx, Shutdown: shutdown, srv: srv, disp: disp, Cleanup: cleanup}
+func NewBridge(ctx *context.T, disp rpc.Dispatcher) *Bridge {
+	return &Bridge{Ctx: ctx, Disp: disp}
 }
 
 func (b *Bridge) NewCtxCall(suffix string, method rpc.MethodDesc) (*context.T, rpc.ServerCall) {
 	ctx, _ := vtrace.WithNewTrace(b.Ctx)
-	return ctx, newFakeServerCall(ctx, b.srv, suffix, method)
-}
-
-func (b *Bridge) Destroy() {
-	b.Cleanup()
-	b.Shutdown()
+	return ctx, newFakeServerCall(ctx, b.Srv, suffix, method)
 }
 
 ////////////////////////////////////////
 // Dispatch-related methods
 
 func (b *Bridge) lookupAndAuthorize(ctx *context.T, call rpc.ServerCall, suffix string) (interface{}, error) {
-	resInt, auth, err := b.disp.Lookup(ctx, suffix)
+	resInt, auth, err := b.Disp.Lookup(ctx, suffix)
 	if err != nil {
 		return nil, err
 	}
diff --git a/services/syncbase/bridge/cgo/impl.go b/services/syncbase/bridge/cgo/impl.go
index caccb96..8c7d5d6 100644
--- a/services/syncbase/bridge/cgo/impl.go
+++ b/services/syncbase/bridge/cgo/impl.go
@@ -71,6 +71,8 @@
 // Global state, initialized by v23_syncbase_Init.
 var (
 	b *bridge.Bridge
+	// rootDir is the root directory for credentials and syncbase storage.
+	rootDir string
 	// clientUnderstandsVOM specifies whether the Cgo layer should assume
 	// the client does VOM encoding and decoding. If false, the Cgo layer
 	// itself does VOM encoding and decoding, and the client deals in byte
@@ -87,25 +89,65 @@
 	// unknown flags passed by Xcode, e.g. NSTreatUnknownArgumentsAsOpen.
 	os.Args = os.Args[:1]
 	ctx, shutdown := v23.Init()
-	srv, disp, cleanup := syncbaselib.Serve(ctx, syncbaselib.Opts{RootDir: cRootDir.extract()})
-	b = bridge.NewBridge(ctx, context.CancelFunc(shutdown), srv, disp, cleanup)
+	b = &bridge.Bridge{Ctx: ctx, Shutdown: shutdown}
+	rootDir = cRootDir.extract()
 	clientUnderstandsVOM = cClientUnderstandVom.extract()
 }
 
+//export v23_syncbase_Serve
+func v23_syncbase_Serve(cErr *C.v23_syncbase_VError) {
+	// TODO(razvanm): Uncomment the check from below after logging is
+	// plumbed through and we have a solution for tests.
+	//
+	//if !isLoggedIn() {
+	//	cErr.init(verror.New(verror.ErrInternal, nil, "not logged in"))
+	//}
+	srv, disp, cleanup := syncbaselib.Serve(b.Ctx, syncbaselib.Opts{
+		// TODO(sadovsky): Make and pass a subdir of rootDir here, so
+		// that rootDir can also be used for credentials persistence.
+		RootDir: rootDir,
+	})
+	b.Srv = srv
+	b.Disp = disp
+	b.Cleanup = cleanup
+}
+
 //export v23_syncbase_Shutdown
 func v23_syncbase_Shutdown() {
-	if b != nil {
-		b.Destroy()
-		b = nil
+	if b == nil {
+		return
 	}
+
+	if b.Cleanup != nil {
+		b.Cleanup()
+		b.Cleanup = nil
+	}
+
+	b.Shutdown()
+	b = nil
 }
 
 ////////////////////////////////////////
 // OAuth
 
+func isLoggedIn() bool {
+	_, _, err := util.AppAndUserPatternFromBlessings(security.DefaultBlessingNames(v23.GetPrincipal(b.Ctx))...)
+	return err == nil
+}
+
+//export v23_syncbase_IsLoggedIn
+func v23_syncbase_IsLoggedIn(cIsLoggedIn *C.v23_syncbase_Bool) {
+	cIsLoggedIn.init(isLoggedIn())
+}
+
 //export v23_syncbase_Login
 func v23_syncbase_Login(cOAuthProvider C.v23_syncbase_String, cOAuthToken C.v23_syncbase_String, cErr *C.v23_syncbase_VError) {
-	cErr.init(bridge.SeekAndSetBlessings(b.Ctx, cOAuthProvider.extract(), cOAuthToken.extract()))
+	err := bridge.SeekAndSetBlessings(b.Ctx, cOAuthProvider.extract(), cOAuthToken.extract())
+	if err != nil {
+		cErr.init(err)
+		return
+	}
+	v23_syncbase_Serve(cErr)
 }
 
 ////////////////////////////////////////
diff --git a/services/syncbase/bridge/cgo/jni.go b/services/syncbase/bridge/cgo/jni.go
index 003ae2a..3c8a6e9 100644
--- a/services/syncbase/bridge/cgo/jni.go
+++ b/services/syncbase/bridge/cgo/jni.go
@@ -101,6 +101,13 @@
 	v23_syncbase_Init(C.v23_syncbase_Bool(1), cInitRoot)
 }
 
+//export Java_io_v_syncbase_internal_Service_Serve
+func Java_io_v_syncbase_internal_Service_Serve(env *C.JNIEnv, cls C.jclass) {
+	var cErr C.v23_syncbase_VError
+	v23_syncbase_Serve(&cErr)
+	maybeThrowException(env, &cErr)
+}
+
 //export Java_io_v_syncbase_internal_Service_Shutdown
 func Java_io_v_syncbase_internal_Service_Shutdown(env *C.JNIEnv, cls C.jclass) {
 	v23_syncbase_Shutdown()
@@ -115,6 +122,13 @@
 	maybeThrowException(env, &cErr)
 }
 
+//export Java_io_v_syncbase_internal_Service_IsLoggedIn
+func Java_io_v_syncbase_internal_Service_IsLoggedIn(env *C.JNIEnv, cls C.jclass) C.jboolean {
+	var r C.v23_syncbase_Bool
+	v23_syncbase_IsLoggedIn(&r)
+	return C.jboolean(r)
+}
+
 //export Java_io_v_syncbase_internal_Service_GetPermissions
 func Java_io_v_syncbase_internal_Service_GetPermissions(env *C.JNIEnv, cls C.jclass) C.jobject {
 	var cPerms C.v23_syncbase_Permissions