diff --git a/rbf.go b/rbf.go index 21c1a321a..4fa2f8900 100644 --- a/rbf.go +++ b/rbf.go @@ -436,7 +436,7 @@ func (tx *RBFTx) GetSortedFieldViewList(idx *Index, shard uint64) (fvs []txkey.F } func (tx *RBFTx) GetFieldSizeBytes(index, field string) (uint64, error) { - return 0, nil + return tx.tx.GetSizeBytesWithPrefix(string(txkey.FieldPrefix(index, field))) } // rbfName returns a NULL-separated key used for identifying bitmap maps in RBF. diff --git a/rbf/tx.go b/rbf/tx.go index f89b38048..5e7c35001 100644 --- a/rbf/tx.go +++ b/rbf/tx.go @@ -839,23 +839,31 @@ func (tx *Tx) inusePageSet() (map[uint32]struct{}, error) { return m, nil } -func (tx *Tx) GetFieldSizeBytes(index, field string) (uint64, error) { - - fmt.Printf("getting RBF field size %s/%s\n", index, field) - - var pgno uint32 - var parent uint32 - - var pageCount uint64 - - if err := tx.walkTree(pgno, parent, func(pgno, parent, typ uint32) error { - pageCount++ - return nil - }); err != nil { +// GetSizeBytesWithPrefix returns the size of bitmaps with a given key prefix. +func (tx *Tx) GetSizeBytesWithPrefix(prefix string) (n uint64, err error) { + records, err := tx.RootRecords() + if err != nil { return 0, err } - return uint64(pageCount * PageSize), nil + // Loop over each bitmap in the database. + for itr := records.Iterator(); !itr.Done(); { + name, pgno := itr.Next() + + // Skip over any bitmaps that don't have a matching prefix. + if !strings.HasPrefix(name.(string), prefix) { + continue + } + + // Traverse the bitmap's b-tree and count the bytes for each page. + if err := tx.walkTree(pgno.(uint32), 0, func(pgno, parent, typ uint32) error { + n += PageSize + return nil + }); err != nil { + return 0, err + } + } + return n, nil } // walkTree recursively iterates over a page and all its children. diff --git a/server/server.go b/server/server.go index 530e4102a..51729a8b1 100644 --- a/server/server.go +++ b/server/server.go @@ -185,7 +185,7 @@ func (m *Command) Start() (err error) { return errors.Wrap(err, "opening server") } - m.logger.Printf("listening as %s\n", m.listenURI) + m.logger.Printf("listening! as %s\n", m.listenURI) go func() { if err := m.grpcServer.Serve(); err != nil { m.logger.Printf("grpc server error: %v", err) diff --git a/txfactory.go b/txfactory.go index 5e2ad647b..a7984e518 100644 --- a/txfactory.go +++ b/txfactory.go @@ -602,15 +602,7 @@ func (f *TxFactory) IndexUsageDetails() (map[string]IndexUsage, error) { idxs := f.holder.Indexes() - /* - qcx := f.NewQcx() - tx, finisher, err := qcx.GetTx(Txo{Write: !writable}) - if err != nil { - return indexUsage, errors.Wrap(err, "qcx.GetTx") - } - defer finisher(nil) - */ - + qcx := f.NewQcx() for _, idx := range idxs { index := idx.name println(" i:" + index) @@ -632,18 +624,30 @@ func (f *TxFactory) IndexUsageDetails() (map[string]IndexUsage, error) { fieldKeysTotal += keysBytes fragmentsTotal += fieldUsages[field].Fragments - // non-roaring field usage - /* - fieldBytes, err := tx.GetFieldSizeBytes(index, field) - if err != nil { - return indexUsage, errors.Wrapf(err, "getting disk usage for non-roaring fragments (%s)", field) + fieldUsage := FieldUsage{Keys: keysBytes} + + for _, shard := range fld.AvailableShards(true).Slice() { + if err := func() error { + tx, finisher, err := qcx.GetTx(Txo{Write: !writable, Index: idx, Shard: shard}) + if err != nil { + return errors.Wrap(err, "qcx.GetTx") + } + defer finisher(nil) + + // non-roaring field usage + fieldBytes, err := tx.GetFieldSizeBytes(index, field) + if err != nil { + return errors.Wrapf(err, "getting disk usage for non-roaring fragments (%s)", field) + } + fieldUsage.Total += fieldBytes + return nil + }(); err != nil { + return indexUsage, err } - fieldUsages[field] = FieldUsage{ - Total: fieldBytes, - Fragments: fieldBytes - keysBytes, - Keys: keysBytes, - } - */ + } + + fieldUsage.Fragments = fieldUsage.Total - keysBytes + fieldUsages[field] = fieldUsage } // index keys usage