From 679d1140cc898cd56f0da663647c57c45fed79c5 Mon Sep 17 00:00:00 2001 From: mappu Date: Sun, 21 May 2017 13:31:28 +1200 Subject: [PATCH] recursive bucket scan - we're crashing when passing a slice to go code --- main.go | 43 +++++++++++++++++------------------------- qbolt/boltdb.cpp | 17 ++++++++++++++++- qbolt/boltdb.h | 6 ++++++ qbolt/interop.cpp | 4 +++- qbolt/mainwindow.cpp | 45 ++++++++++++++++++++++++++++++-------------- 5 files changed, 73 insertions(+), 42 deletions(-) diff --git a/main.go b/main.go index c3390b5..6278125 100644 --- a/main.go +++ b/main.go @@ -160,38 +160,29 @@ func Bolt_ListBuckets(b ObjectReference, browse []string) ObjectReference { pNC_Ref := gms.Put(pNC) go func() { - err := withBoltDBReference(b, func(db *bolt.DB) error { - return db.View(func(tx *bolt.Tx) error { + var err error - if len(browse) == 0 { - // Root-mode + if len(browse) == 0 { + // root mode + err = withBoltDBReference(b, func(db *bolt.DB) error { + return db.View(func(tx *bolt.Tx) error { 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])) - if bucket == nil { - return errors.New("Unknown bucket") - } - - for i := 1; i < len(browse); i += 1 { - bucket = bucket.Bucket([]byte(browse[i])) - if bucket == nil { - return errors.New("Unknown bucket") - } - } - - return bucket.ForEach(func(k, v []byte) error { - pNC.content <- CallResponse{s: string(k)} - return nil - }) - - } + }) }) - }) + + } else { + // Nested-mode + err = withBrowse_ReadOnly(b, browse, func(db *bolt.DB, tx *bolt.Tx, bucket *bolt.Bucket) error { + return bucket.ForEach(func(k, v []byte) error { + pNC.content <- CallResponse{s: string(k)} + return nil + }) + }) + + } if err != nil { pNC.content <- CallResponse{e: err} diff --git a/qbolt/boltdb.cpp b/qbolt/boltdb.cpp index a37cda8..9d85af8 100644 --- a/qbolt/boltdb.cpp +++ b/qbolt/boltdb.cpp @@ -32,11 +32,26 @@ static const int REAL_MESSAGE = 103; bool BoltDB::listBucketsAtRoot(QString& errorOut, NameReciever cb) { auto listJob = ::Bolt_ListBucketsAtRoot(this->gmsDbRef); + return pumpNext(listJob, errorOut, cb); +} +bool BoltDB::listBuckets(QStringList bucketPath, QString& errorOut, NameReciever cb) +{ + if (bucketPath.size() == 0) { + return listBucketsAtRoot(errorOut, cb); + } + + GoSliceManagedWrapper browse(&bucketPath); + auto listJob = ::Bolt_ListBuckets(this->gmsDbRef, browse.slice); + return pumpNext(listJob, errorOut, cb); +} + +bool BoltDB::pumpNext(GoInt64 jobRef, QString& errorOut, NameReciever cb) +{ errorOut.clear(); for(;;) { - auto gnr = ::GetNext(listJob); + auto gnr = ::GetNext(jobRef); if (gnr.r0 == ERROR_AND_STOP_CALLING) { errorOut.append(QString::fromUtf8(gnr.r1, gnr.r2)); // log error diff --git a/qbolt/boltdb.h b/qbolt/boltdb.h index 379c4b6..2836396 100644 --- a/qbolt/boltdb.h +++ b/qbolt/boltdb.h @@ -18,11 +18,17 @@ public: bool listBucketsAtRoot(QString& errorOut, NameReciever cb); + bool listBuckets(QStringList bucketPath, QString& errorOut, NameReciever cb); + bool getStatsJSON(std::function onSuccess, std::function onError); bool getBucketStatsJSON(QStringList bucketPath, std::function onSuccess, std::function onError); ~BoltDB(); + +protected: + + bool pumpNext(GoInt64 jobRef, QString& errorOut, NameReciever cb); }; #endif // BOLTDB_H diff --git a/qbolt/interop.cpp b/qbolt/interop.cpp index bed064d..b91e1f0 100644 --- a/qbolt/interop.cpp +++ b/qbolt/interop.cpp @@ -22,12 +22,14 @@ GoSliceManagedWrapper::GoSliceManagedWrapper(QStringList *qsl) : strings(), slice() { + rawStrings.reserve(qsl->size()); + strings.reserve(qsl->size()); for (int i = 0; i < qsl->size(); ++i) { rawStrings.push_back( qsl->at(i).toUtf8() ); strings.push_back(GoString{ rawStrings[i].data(), rawStrings[i].size() }); } - slice.data = static_cast( & strings.first() ); + slice.data = static_cast( & strings[0] ); slice.len = strings.size(); // * sizeof(GoString); slice.cap = slice.len; } diff --git a/qbolt/mainwindow.cpp b/qbolt/mainwindow.cpp index 68add78..50a8100 100644 --- a/qbolt/mainwindow.cpp +++ b/qbolt/mainwindow.cpp @@ -65,26 +65,43 @@ void MainWindow::on_actionOpen_database_triggered() ui->bucketTree->addTopLevelItem(top); refreshBucketTree(top); + ui->bucketTree->setCurrentItem(top); } -void MainWindow::refreshBucketTree(QTreeWidgetItem* top) +void MainWindow::refreshBucketTree(QTreeWidgetItem* itm) { - ui->bucketTree->clearSelection(); - //top->setSelected(true); - ui->bucketTree->setCurrentItem(top); - - auto *bdb = GET_BDB(top); - for (int i = top->childCount(); i --> 0;) { - delete top->takeChild(i); + // ui->bucketTree->clearSelection(); + QTreeWidgetItem *top = itm; + QStringList browsePath; + while(top->parent() != nullptr) { + browsePath.push_front(top->text(0)); + top = top->parent(); } + // Remove existing children + for (int i = itm->childCount(); i --> 0;) { + delete itm->takeChild(i); + } + + if (browsePath.size() > 1) { + return; // only go one level deep + } + + auto *bdb = GET_BDB(top); + QString error; - bool ok = bdb->listBucketsAtRoot(error, [=](QByteArray qba){ - QTreeWidgetItem *child = new QTreeWidgetItem(); - child->setText(0, QString::fromUtf8(qba)); - child->setIcon(0, QIcon(":/rsrc/table.png")); - top->addChild(child); - }); + bool ok = bdb->listBuckets( + browsePath, + error, + [=](QByteArray qba){ + QTreeWidgetItem *child = new QTreeWidgetItem(); + child->setText(0, QString::fromUtf8(qba)); + child->setIcon(0, QIcon(":/rsrc/table.png")); + itm->addChild(child); + + refreshBucketTree(child); + } + ); if (!ok) { QMessageBox qmb;