v.io/x/jni: Support for the ref fix
MultiPart: 2/2
Change-Id: I5cc7838fd4912fc7f79420ca8a7b4b26f23e091d
diff --git a/impl/google/channel/jni.go b/impl/google/channel/jni.go
index b9b3bee..4daff97 100644
--- a/impl/google/channel/jni.go
+++ b/impl/google/channel/jni.go
@@ -10,6 +10,7 @@
"fmt"
"unsafe"
+ "v.io/v23/verror"
jutil "v.io/x/jni/util"
)
@@ -46,30 +47,31 @@
}
//export Java_io_v_impl_google_channel_ChannelIterable_nativeReadValue
-func Java_io_v_impl_google_channel_ChannelIterable_nativeReadValue(jenv *C.JNIEnv, jChannelIterable C.jobject, goValChanPtr C.jlong, goErrChanPtr C.jlong) C.jobject {
+func Java_io_v_impl_google_channel_ChannelIterable_nativeReadValue(jenv *C.JNIEnv, jChannelIterable C.jobject, goChanPtr C.jlong, goConvertPtr C.jlong) C.jobject {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
- valCh := *(*chan jutil.Object)(jutil.NativePtr(goValChanPtr))
- errCh := *(*chan error)(jutil.NativePtr(goErrChanPtr))
- if jObj, ok := <-valCh; ok {
- jObjLocal := jutil.NewLocalRef(env, jObj)
- jutil.DeleteGlobalRef(env, jObj)
- return C.jobject(unsafe.Pointer(jObjLocal))
+ c := *(*chan interface{})(jutil.NativePtr(goChanPtr))
+ convert := *(*func(jutil.Env, interface{})(jutil.Object, error))(jutil.NativePtr(goConvertPtr))
+ val, ok := <-c
+ if !ok { // channel closed
+ jutil.JThrow(env, jEOFExceptionClass, "Reached end of input channel.")
+ return nil
}
- // No more results, figure out if gracefully or due to an error.
- err, ok := <-errCh
- if !ok { // gracefully
- jutil.JThrow(env, jEOFExceptionClass, "Channel closed.")
- } else { // error
- jutil.JThrowV(env, err)
+ jVal, err := convert(env, val)
+ if err == nil {
+ return C.jobject(unsafe.Pointer(jVal))
}
+ if verr, ok := err.(verror.E); ok && verr.ID == verror.ErrCanceled.ID { // EOF
+ jutil.JThrow(env, jEOFExceptionClass, "User canceled the operation.")
+ return nil
+ }
+ jutil.JThrowV(env, err)
return nil
}
//export Java_io_v_impl_google_channel_ChannelIterable_nativeFinalize
-func Java_io_v_impl_google_channel_ChannelIterable_nativeFinalize(jenv *C.JNIEnv, jChannelIterable C.jobject, goValChanPtr C.jlong, goErrChanPtr C.jlong, goSourceChanPtr C.jlong) {
- jutil.GoUnref(jutil.NativePtr(goValChanPtr))
- jutil.GoUnref(jutil.NativePtr(goErrChanPtr))
- jutil.GoUnref(jutil.NativePtr(goSourceChanPtr))
+func Java_io_v_impl_google_channel_ChannelIterable_nativeFinalize(jenv *C.JNIEnv, jChannelIterable C.jobject, goChanPtr C.jlong, goConvertPtr C.jlong) {
+ jutil.GoUnref(jutil.NativePtr(goChanPtr))
+ jutil.GoUnref(jutil.NativePtr(goConvertPtr))
}
//export Java_io_v_impl_google_channel_OutputChannelImpl_nativeWriteValue
diff --git a/impl/google/channel/util.go b/impl/google/channel/util.go
index 4a4d007..331d542 100644
--- a/impl/google/channel/util.go
+++ b/impl/google/channel/util.go
@@ -13,16 +13,15 @@
// #include "jni.h"
import "C"
-// JavaIterable converts the provided Go channel of jutil.Object values into a Java
-// VIterable object.
-func JavaIterable(env jutil.Env, valChPtr, errChPtr, sourceChPtr interface{}) (jutil.Object, error) {
- jIterable, err := jutil.NewObject(env, jChannelIterableClass, []jutil.Sign{jutil.LongSign, jutil.LongSign, jutil.LongSign}, int64(jutil.PtrValue(valChPtr)), int64(jutil.PtrValue(errChPtr)), int64(jutil.PtrValue(sourceChPtr)))
+// JavaIterable converts the provided Go channel into a Java VIterable object, using the
+// given convert function.
+func JavaIterable(env jutil.Env, ch chan interface{}, convert func(jutil.Env, interface{}) (jutil.Object, error)) (jutil.Object, error) {
+ jIterable, err := jutil.NewObject(env, jChannelIterableClass, []jutil.Sign{jutil.LongSign, jutil.LongSign}, int64(jutil.PtrValue(&ch)), int64(jutil.PtrValue(&convert)))
if err != nil {
return jutil.NullObject, err
}
- jutil.GoRef(valChPtr) // Un-refed when ChannelIterable is finalized.
- jutil.GoRef(errChPtr) // Un-refed when ChannelIterable is finalized.
- jutil.GoRef(sourceChPtr) // Un-refed when ChannelIterable is finalized.
+ jutil.GoRef(&ch) // Un-refed when ChannelIterable is finalized.
+ jutil.GoRef(&convert) // Un-refed when ChannelIterable is finalized.
return jIterable, nil
}
diff --git a/impl/google/namespace/jni.go b/impl/google/namespace/jni.go
index 2eeaf66..dad54ce 100644
--- a/impl/google/namespace/jni.go
+++ b/impl/google/namespace/jni.go
@@ -72,44 +72,30 @@
}
func doGlob(env jutil.Env, n namespace.T, context *context.T, pattern string, opts []naming.NamespaceOpt) (jutil.Object, error) {
- entryChan, err := n.Glob(context, pattern, opts...)
+ c, err := n.Glob(context, pattern, opts...)
if err != nil {
return jutil.NullObject, err
}
-
- valChan := make(chan jutil.Object, 5)
- errChan := make(chan error, 1)
+ valChan := make(chan interface{}, 100)
go func() {
- env, freeFunc := jutil.GetEnv()
- defer freeFunc()
-
- for globReply := range entryChan {
- // Check for a canceled context error, we surface these as EOF.
- if errorEntry, ok := globReply.(*naming.GlobReplyError); ok {
- if verr, ok := errorEntry.Value.Error.(verror.E); ok && verr.ID == verror.ErrCanceled.ID {
- break
- }
- }
- jGlobReply, err := jutil.JVomCopy(env, globReply, jGlobReplyClass)
- if err != nil {
- errChan <- fmt.Errorf("Couldn't convert Go glob result %v to Java: %v\n", globReply, err)
- break
- }
- // The other side of the channel is responsible for deleting this
- // global reference.
- valChan <- jutil.NewGlobalRef(env, jGlobReply)
- // Free up the local reference as it'll be auto-freed only when
- // freeFunc() gets executed, which can burn us for big globs.
- jutil.DeleteLocalRef(env, jGlobReply)
+ for val := range c {
+ valChan <- val
}
close(valChan)
- close(errChan)
}()
- jIterable, err := jchannel.JavaIterable(env, &valChan, &errChan, &entryChan)
- if err != nil {
- return jutil.NullObject, err
- }
- return jIterable, nil
+ return jchannel.JavaIterable(env, valChan, func(env jutil.Env, val interface{}) (jutil.Object, error) {
+ globReply, ok := val.(naming.GlobReply)
+ if !ok {
+ return jutil.NullObject, fmt.Errorf("Expected value of GlobReply type, got type %T: %v", val, val)
+ }
+ // Check for a canceled context error, we surface these as EOF.
+ if errorEntry, ok := globReply.(*naming.GlobReplyError); ok {
+ if verr, ok := errorEntry.Value.Error.(verror.E); ok && verr.ID == verror.ErrCanceled.ID {
+ return jutil.NullObject, verr
+ }
+ }
+ return jutil.JVomCopy(env, val, jGlobReplyClass)
+ })
}
//export Java_io_v_impl_google_namespace_NamespaceImpl_nativeGlob