retrieve bucket properties

This commit is contained in:
mappu 2017-05-21 12:39:55 +12:00
parent 95a1bfeea5
commit 60d71104e8
8 changed files with 246 additions and 62 deletions

49
main.go
View File

@ -76,6 +76,34 @@ func withBoltDBReference(b ObjectReference, fn func(db *bolt.DB) error) error {
return fn(ptrDB)
}
func withBrowse_ReadOnly(b_ref ObjectReference, browse []string, fn func(db *bolt.DB, tx *bolt.Tx, bucket *bolt.Bucket) error) error {
if len(browse) == 0 {
// not a bucket
return errors.New("No bucket selected")
}
return withBoltDBReference(b_ref, func(db *bolt.DB) error {
return db.View(func(tx *bolt.Tx) error {
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")
}
}
// Walked the bucket chain, now run the user callback
return fn(db, tx, bucket)
})
})
}
type CallResponse struct {
s string
e error
@ -98,6 +126,27 @@ func Bolt_DBStats(b ObjectReference) (int64, *C.char, int) {
return REAL_MESSAGE, C.CString(string(jBytes)), len(jBytes)
}
//export Bolt_BucketStats
func Bolt_BucketStats(b ObjectReference, browse []string) (int64, *C.char, int) {
var stats bolt.BucketStats
err := withBrowse_ReadOnly(b, browse, func(db *bolt.DB, tx *bolt.Tx, bucket *bolt.Bucket) error {
stats = bucket.Stats()
return nil
})
if err != nil {
return ERROR_AND_STOP_CALLING, C.CString(err.Error()), len(err.Error())
}
jBytes, err := json.Marshal(stats)
if err != nil {
return ERROR_AND_STOP_CALLING, C.CString(err.Error()), len(err.Error())
}
return REAL_MESSAGE, C.CString(string(jBytes)), len(jBytes)
}
type NextCall struct {
content chan CallResponse
}

View File

@ -76,6 +76,15 @@ struct Bolt_DBStats_return {
extern struct Bolt_DBStats_return Bolt_DBStats(GoInt64 p0);
/* Return type for Bolt_BucketStats */
struct Bolt_BucketStats_return {
GoInt64 r0;
char* r1;
GoInt r2;
};
extern struct Bolt_BucketStats_return Bolt_BucketStats(GoInt64 p0, GoSlice p1);
extern GoInt64 Bolt_ListBuckets(GoInt64 p0, GoSlice p1);
/* Return type for GetNext */

View File

@ -84,6 +84,29 @@ bool BoltDB::getStatsJSON(std::function<void(QString)> onSuccess, std::function<
}
}
bool BoltDB::getBucketStatsJSON(QStringList bucketPath, std::function<void(QString)> onSuccess, std::function<void(QString)> onError)
{
GoSliceManagedWrapper sliceWrapper(&bucketPath);
auto statresp = Bolt_BucketStats(this->gmsDbRef, sliceWrapper.slice);
if (statresp.r0 == ERROR_AND_STOP_CALLING) {
QString err = QString::fromUtf8(statresp.r1, statresp.r2);
free(statresp.r1);
onError(err);
return false;
} else if (statresp.r0 == REAL_MESSAGE) {
QString json = QString::fromUtf8(statresp.r1, statresp.r2);
free(statresp.r1);
onSuccess(json);
return true;
} else {
// ?? shouldn't be reachable
return false;
}
}
BoltDB::~BoltDB()
{
auto err = ::Bolt_Close(this->gmsDbRef);

View File

@ -20,6 +20,8 @@ public:
bool getStatsJSON(std::function<void(QString)> onSuccess, std::function<void(QString)> onError);
bool getBucketStatsJSON(QStringList bucketPath, std::function<void(QString)> onSuccess, std::function<void(QString)> onError);
~BoltDB();
};

View File

@ -1,5 +1,7 @@
#include "interop.h"
#include <QStringList>
Interop::Interop()
{
@ -12,3 +14,20 @@ GoString Interop::toGoString_WeakRef(QByteArray *qba) {
int64_t Interop::GetMagic() {
return ::GetMagic();
}
//
GoSliceManagedWrapper::GoSliceManagedWrapper(QStringList *qsl) :
rawStrings(),
strings(),
slice()
{
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<void*>( & strings.first() );
slice.len = strings.size(); // * sizeof(GoString);
slice.cap = slice.len;
}

View File

@ -3,6 +3,19 @@
#include "../qbolt.h"
#include <QString>
#include <QList>
class GoSliceManagedWrapper {
Q_DISABLE_COPY(GoSliceManagedWrapper)
public:
GoSliceManagedWrapper(QStringList *qsl);
protected:
QList<QByteArray> rawStrings;
QList<GoString> strings;
public:
GoSlice slice;
};
class Interop
{

View File

@ -31,6 +31,15 @@ static const int BdbPointerRole = Qt::UserRole + 1;
#define SET_BDB(top, bdb) top->setData(0, BdbPointerRole, QVariant::fromValue<void*>(static_cast<void*>(bdb)))
#define GET_BDB(top) static_cast<BoltDB*>( top->data(0, BdbPointerRole).value<void*>() )
/*
static BoltDB* GET_BDB(QTreeWidgetItem *top) {
while(top->parent() != nullptr) {
top = top->parent();
}
return static_cast<BoltDB*>( top->data(0, BdbPointerRole).value<void*>() );
}
*/
void MainWindow::on_actionOpen_database_triggered()
{
@ -152,32 +161,58 @@ void MainWindow::on_bucketTree_currentItemChanged(QTreeWidgetItem *current, QTre
{
Q_UNUSED(previous);
if (current == nullptr) {
ui->tabWidget->setVisible(false);
ui->stackedWidget->setVisible(false);
return;
}
ui->tabWidget->setVisible(true);
ui->stackedWidget->setVisible(true);
if (current->parent() == nullptr) {
// Selected a database
ui->stackedWidget->setCurrentWidget(ui->databasePage);
auto *bdb = GET_BDB(current);
ui->propertiesArea->clear();
bdb->getStatsJSON([=](QString j) {
ui->propertiesArea->setPlainText(j);
}, [=](QString error) {
QMessageBox qmb;
qmb.setText(tr("Error retrieving database statistics: %1").arg(error));
qmb.exec();
});
bdb->getStatsJSON(
[=](QString j) {
ui->databasePropertiesArea->clear();
ui->databasePropertiesArea->setPlainText(j);
},
[=](QString error) {
QMessageBox qmb;
qmb.setText(tr("Error retrieving database statistics: %1").arg(error));
qmb.exec();
}
);
} else {
// Selected a bucket
ui->stackedWidget->setCurrentWidget(ui->bucketPage);
QStringList browse;
QTreeWidgetItem *top = current;
while (top->parent() != nullptr) {
browse.push_front(top->text(0));
top = top->parent();
}
auto *bdb = GET_BDB(top);
bdb->getBucketStatsJSON(
browse,
[=](QString j) {
ui->bucketPropertiesArea->clear();
ui->bucketPropertiesArea->setPlainText(j);
},
[=](QString error) {
QMessageBox qmb;
qmb.setText(tr("Error retrieving bucket statistics: %1").arg(error));
qmb.exec();
}
);
// Load the data tab
// TODO
ui->propertiesArea->clear();
}
// refresh properties for the currently selected tree item...
}
void MainWindow::on_actionClear_selection_triggered()

View File

@ -52,81 +52,115 @@
</property>
</column>
</widget>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="propertiesTab">
<attribute name="title">
<string>Properties</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<widget class="QStackedWidget" name="stackedWidget">
<widget class="QWidget" name="databasePage">
<layout class="QGridLayout" name="gridLayout_4">
<property name="leftMargin">
<number>3</number>
<number>0</number>
</property>
<property name="topMargin">
<number>3</number>
<number>0</number>
</property>
<property name="rightMargin">
<number>3</number>
<number>0</number>
</property>
<property name="bottomMargin">
<number>3</number>
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QPlainTextEdit" name="propertiesArea">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="plainText">
<string>No selection</string>
<widget class="QTabWidget" name="databaseTabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="databasePropertiesTab">
<attribute name="title">
<string>Database</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item row="0" column="0">
<widget class="QPlainTextEdit" name="databasePropertiesArea">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="plainText">
<string>No selection</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="dataTab">
<attribute name="title">
<string>Data</string>
</attribute>
<widget class="QWidget" name="bucketPage">
<layout class="QGridLayout" name="gridLayout_3">
<property name="leftMargin">
<number>3</number>
<number>0</number>
</property>
<property name="topMargin">
<number>3</number>
<number>0</number>
</property>
<property name="rightMargin">
<number>3</number>
<number>0</number>
</property>
<property name="bottomMargin">
<number>3</number>
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QTreeWidget" name="treeWidget">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="indentation">
<widget class="QTabWidget" name="bucketTabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<property name="rootIsDecorated">
<bool>false</bool>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
<widget class="QWidget" name="bucketPropertiesTab">
<attribute name="title">
<string>Bucket</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_5">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item row="0" column="0">
<widget class="QPlainTextEdit" name="bucketPropertiesArea">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="bucketDataTab">
<attribute name="title">
<string>Data</string>
</attribute>
</widget>
</widget>
</item>
</layout>