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