convert cgo function pointer call to repeated iteration
This commit is contained in:
parent
be594cb1a5
commit
3911d7d66c
89
main.go
89
main.go
@ -68,15 +68,36 @@ func withBoltDBReference(b ObjectReference, fn func(db *bolt.DB) error) error {
|
|||||||
return fn(ptrDB)
|
return fn(ptrDB)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CallResponse struct {
|
||||||
|
s string
|
||||||
|
e error
|
||||||
|
}
|
||||||
|
|
||||||
|
type NextCall struct {
|
||||||
|
content chan CallResponse
|
||||||
|
}
|
||||||
|
|
||||||
//export Bolt_ListBuckets
|
//export Bolt_ListBuckets
|
||||||
func Bolt_ListBuckets(b ObjectReference, browse []string, ctx uintptr, withEach func(uintptr, string)) string {
|
func Bolt_ListBuckets(b ObjectReference, browse []string) ObjectReference {
|
||||||
if len(browse) == 0 {
|
pNC := &NextCall{
|
||||||
return Bolt_ListBucketsAtRoot(b, ctx, withEach)
|
content: make(chan CallResponse, 0),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pNC_Ref := gms.Put(pNC)
|
||||||
|
|
||||||
|
go func() {
|
||||||
err := withBoltDBReference(b, func(db *bolt.DB) error {
|
err := withBoltDBReference(b, func(db *bolt.DB) error {
|
||||||
return db.View(func(tx *bolt.Tx) error {
|
return db.View(func(tx *bolt.Tx) error {
|
||||||
|
|
||||||
|
if len(browse) == 0 {
|
||||||
|
// Root-mode
|
||||||
|
return tx.ForEach(func(k []byte, _ *bolt.Bucket) error {
|
||||||
|
pNC.content <- CallResponse{s: string(k)}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Nested-mode
|
||||||
bucket := tx.Bucket([]byte(browse[0]))
|
bucket := tx.Bucket([]byte(browse[0]))
|
||||||
if bucket == nil {
|
if bucket == nil {
|
||||||
return errors.New("Unknown bucket")
|
return errors.New("Unknown bucket")
|
||||||
@ -90,39 +111,59 @@ func Bolt_ListBuckets(b ObjectReference, browse []string, ctx uintptr, withEach
|
|||||||
}
|
}
|
||||||
|
|
||||||
return bucket.ForEach(func(k, v []byte) error {
|
return bucket.ForEach(func(k, v []byte) error {
|
||||||
|
pNC.content <- CallResponse{s: string(k)}
|
||||||
withEach(ctx, string(k))
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err.Error()
|
pNC.content <- CallResponse{e: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ""
|
close(pNC.content)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return pNC_Ref
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
ERROR_AND_STOP_CALLING int = 100
|
||||||
|
ERROR_AND_KEEP_CALLING = 101
|
||||||
|
FINISHED_OK = 102
|
||||||
|
REAL_MESSAGE = 103
|
||||||
|
)
|
||||||
|
|
||||||
|
//export GetNext
|
||||||
|
func GetNext(oRef ObjectReference) (int, string) {
|
||||||
|
pNC_Iface, ok := gms.Get(oRef)
|
||||||
|
if !ok {
|
||||||
|
return ERROR_AND_STOP_CALLING, NullObjectReference.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
pNC, ok := pNC_Iface.(*NextCall)
|
||||||
|
if !ok {
|
||||||
|
return ERROR_AND_STOP_CALLING, NullObjectReference.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
cr, ok := <-pNC.content
|
||||||
|
if !ok {
|
||||||
|
gms.Delete(oRef)
|
||||||
|
return FINISHED_OK, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if cr.e != nil {
|
||||||
|
return ERROR_AND_KEEP_CALLING, cr.e.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
return REAL_MESSAGE, cr.s
|
||||||
}
|
}
|
||||||
|
|
||||||
//export Bolt_ListBucketsAtRoot
|
//export Bolt_ListBucketsAtRoot
|
||||||
func Bolt_ListBucketsAtRoot(b ObjectReference, ctx uintptr, withEach func(uintptr, string)) string {
|
func Bolt_ListBucketsAtRoot(b ObjectReference) ObjectReference {
|
||||||
err := withBoltDBReference(b, func(db *bolt.DB) error {
|
return Bolt_ListBuckets(b, nil)
|
||||||
return db.View(func(tx *bolt.Tx) error {
|
|
||||||
|
|
||||||
return tx.ForEach(func(n []byte, bucket *bolt.Bucket) error {
|
|
||||||
|
|
||||||
withEach(ctx, string(n))
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err.Error()
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//export Bolt_Close
|
//export Bolt_Close
|
||||||
|
12
qbolt.h
12
qbolt.h
@ -68,9 +68,17 @@ struct Bolt_Open_return {
|
|||||||
|
|
||||||
extern struct Bolt_Open_return Bolt_Open(GoString p0, GoUint32 p1, GoInt64 p2);
|
extern struct Bolt_Open_return Bolt_Open(GoString p0, GoUint32 p1, GoInt64 p2);
|
||||||
|
|
||||||
extern GoString Bolt_ListBuckets(GoInt64 p0, GoSlice p1, GoUintptr p2, void* p3);
|
extern GoInt64 Bolt_ListBuckets(GoInt64 p0, GoSlice p1);
|
||||||
|
|
||||||
extern GoString Bolt_ListBucketsAtRoot(GoInt64 p0, GoUintptr p1, void* p2);
|
/* Return type for GetNext */
|
||||||
|
struct GetNext_return {
|
||||||
|
GoInt r0;
|
||||||
|
GoString r1;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct GetNext_return GetNext(GoInt64 p0);
|
||||||
|
|
||||||
|
extern GoInt64 Bolt_ListBucketsAtRoot(GoInt64 p0);
|
||||||
|
|
||||||
extern GoString Bolt_Close(GoInt64 p0);
|
extern GoString Bolt_Close(GoInt64 p0);
|
||||||
|
|
||||||
|
@ -23,32 +23,39 @@ BoltDB* BoltDB::createFrom(QString filePath, QString &errorOut)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
static const int ERROR_AND_STOP_CALLING = 100;
|
||||||
struct Wrapper {
|
static const int ERROR_AND_KEEP_CALLING = 101;
|
||||||
T t;
|
static const int FINISHED_OK = 102;
|
||||||
};
|
static const int REAL_MESSAGE = 103;
|
||||||
|
|
||||||
static void byteArrayCallback(void* ctx, GoString text) {
|
|
||||||
auto fn = static_cast<Wrapper<NameReciever>*>(ctx);
|
|
||||||
fn->t(QByteArray::fromRawData(text.p, text.n));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BoltDB::listBucketsAtRoot(QString& errorOut, NameReciever cb)
|
bool BoltDB::listBucketsAtRoot(QString& errorOut, NameReciever cb)
|
||||||
{
|
{
|
||||||
auto containerVar = Wrapper<NameReciever>{cb};
|
auto listJob = ::Bolt_ListBucketsAtRoot(this->gmsDbRef);
|
||||||
|
|
||||||
GoString err = ::Bolt_ListBucketsAtRoot(
|
errorOut.clear();
|
||||||
this->gmsDbRef,
|
|
||||||
(GoUintptr)(&containerVar),
|
|
||||||
byteArrayCallback // -fpermissive
|
|
||||||
);
|
|
||||||
|
|
||||||
if (err.n > 0) {
|
for(;;) {
|
||||||
errorOut = QString(err.p);
|
auto gnr = ::GetNext(listJob);
|
||||||
return false;
|
|
||||||
|
if (gnr.r0 == ERROR_AND_STOP_CALLING) {
|
||||||
|
errorOut.append(QString(gnr.r1.p)); // log error
|
||||||
|
break; // done
|
||||||
|
|
||||||
|
} else if (gnr.r0 == ERROR_AND_KEEP_CALLING) {
|
||||||
|
errorOut.append(QString(gnr.r1.p)); // log error
|
||||||
|
continue;
|
||||||
|
|
||||||
|
} else if (gnr.r0 == FINISHED_OK) {
|
||||||
|
// Once we hit this, the go-side will clean up the channel / associated goroutines
|
||||||
|
break;
|
||||||
|
|
||||||
|
} else if (gnr.r0 == REAL_MESSAGE) {
|
||||||
|
cb(QByteArray(gnr.r1.p, gnr.r1.n));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return (errorOut.length() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
BoltDB::~BoltDB()
|
BoltDB::~BoltDB()
|
||||||
|
Loading…
Reference in New Issue
Block a user