diff --git a/cmd/rbf.go b/cmd/rbf.go index 5cccb7de0..b7c1925c4 100644 --- a/cmd/rbf.go +++ b/cmd/rbf.go @@ -24,7 +24,6 @@ Provides a set of commands for inspecting RBF data files. cmd.AddCommand(newRBFDumpCommand(stdin, stdout, stderr)) cmd.AddCommand(newRBFPagesCommand(stdin, stdout, stderr)) cmd.AddCommand(newRBFPageCommand(stdin, stdout, stderr)) - cmd.AddCommand(newRBFVizCommand(stdin, stdout, stderr)) return cmd } @@ -146,27 +145,3 @@ Prints the header & cell data for one or more pages. } return cmd } - -func newRBFVizCommand(stdin io.Reader, stdout, stderr io.Writer) *cobra.Command { - c := ctl.NewRBFVizCommand(stdin, stdout, stderr) - cmd := &cobra.Command{ - Use: "viz [flags] PATH", - Short: "Show visualization of RBF data. Experimental.", - Long: ` -Show visualization of RBF data. Experimental, do not depend on specifics of the output or the flags of this command. -`, - Args: func(cmd *cobra.Command, args []string) error { - if len(args) == 0 { - return fmt.Errorf("data directory path required") - } else if len(args) > 1 { - return fmt.Errorf("too many command line arguments") - } - c.Path = args[0] - return nil - }, - RunE: func(cmd *cobra.Command, args []string) error { - return c.Run(context.Background()) - }, - } - return cmd -} diff --git a/ctl/rbf_viz.go b/ctl/rbf_viz.go deleted file mode 100644 index aa957e64c..000000000 --- a/ctl/rbf_viz.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2021 Molecula Corp. All rights reserved. -package ctl - -import ( - "context" - "fmt" - "io" - - pilosa "github.com/molecula/featurebase/v3" - "github.com/molecula/featurebase/v3/rbf" -) - -// RBFVizCommand represents a command for doing a visualisation of the RBF tree. -type RBFVizCommand struct { - // Filepath to the RBF database. - Path string - - // Standard input/output - *pilosa.CmdIO -} - -// NewRBFVizCommand returns a new instance of RBFVizCommand. -func NewRBFVizCommand(stdin io.Reader, stdout, stderr io.Writer) *RBFVizCommand { - return &RBFVizCommand{ - CmdIO: pilosa.NewCmdIO(stdin, stdout, stderr), - } -} - -// Run executes a consistency viz of an RBF database. -func (cmd *RBFVizCommand) Run(ctx context.Context) error { - // Open database. - db := rbf.NewDB(cmd.Path, nil) - if err := db.Open(); err != nil { - return err - } - defer db.Close() - - // Run viz on the database. - if err := db.Viz(cmd.Stdout); err != nil { - switch err := err.(type) { - case rbf.ErrorList: - for i := range err { - fmt.Fprintln(cmd.Stdout, err[i]) - } - default: - fmt.Fprintln(cmd.Stdout, err) - } - return fmt.Errorf("viz failed") - } - - return nil -} diff --git a/rbf/db.go b/rbf/db.go index 33eeffd89..d13a0a84c 100644 --- a/rbf/db.go +++ b/rbf/db.go @@ -807,18 +807,6 @@ func (db *DB) Check() error { return tx.Check() } -// Viz writes a graphiz(dot) formatted visualisation of the RBF tree -// to w. At the time of writing this is very preliminary... feel free -// to hack on it and make changes. -func (db *DB) Viz(w io.Writer) error { - tx, err := db.Begin(false) - if err != nil { - return errors.Wrap(err, "beginning transaction") - } - defer tx.Rollback() - return tx.Viz(w) -} - // writeDBPage writes a page to the data file. func (db *DB) writeDBPage(pgno uint32, page []byte) error { _, err := db.file.WriteAt(page, int64(pgno)*PageSize) diff --git a/rbf/rbf.go b/rbf/rbf.go index b7f9c80f4..2778a6592 100644 --- a/rbf/rbf.go +++ b/rbf/rbf.go @@ -43,8 +43,6 @@ const ( const maxBranchCellsPerPage = int((PageSize - branchPageHeaderSize) / (branchCellIndexElemSize + unsafe.Sizeof(branchCell{}))) -type PageType uint32 - // Page types. const ( PageTypeRootRecord = 1 @@ -54,24 +52,6 @@ const ( PageTypeBitmap = 16 // Only used internally when walking the b-tree ) -func (typ PageType) String() string { - switch typ { - case PageTypeRootRecord: - return "root-record" - case PageTypeLeaf: - return "leaf" - case PageTypeBranch: - return "branch" - case PageTypeBitmapHeader: - return "bitmap-header" - case PageTypeBitmap: - return "bitmap" - default: - return fmt.Sprintf("unknown<%d>", typ) - } - -} - // Meta commit/rollback flags. const ( MetaPageFlagCommit = 1 diff --git a/rbf/viz.go b/rbf/viz.go deleted file mode 100644 index 5decbf39a..000000000 --- a/rbf/viz.go +++ /dev/null @@ -1,131 +0,0 @@ -package rbf - -import ( - "fmt" - "io" - - "github.com/pkg/errors" -) - -func (tx *Tx) Viz(w io.Writer) error { - b := &builder{Writer: w} - b.start() - defer b.finish() - - roots, err := tx.RootRecords() - if err != nil { - return errors.Wrap(err, "root records") - } - - itr := roots.Iterator() - - // we use page numbers for graphviz node IDs, but for cells we - // need something different so we start very high assuming it - // won't overlap - cid := &cellID{id: 1 << 48} - - for name, pgno := itr.Next(); name != nil; name, pgno = itr.Next() { - err := tx.walkTree(pgno.(uint32), 0, func(pgno, parent, typ uint32, err error) error { - page, _, err := tx.readPage(pgno) - if err != nil { - return errors.Wrap(err, "reading page") - } - node := &vizNode{ - pgno: pgno, - typ: PageType(typ).String(), - } - if parent == 0 { - node.name = name.(string) - } - node.cellN = readCellN(page) - switch typ { - case PageTypeBitmap: - return nil - case PageTypeLeaf: - numBitmaps := 0 - for i, n := 0, readCellN(page); i < n; i++ { - if cell := readLeafCell(page, i); cell.Type == ContainerTypeBitmapPtr { - numBitmaps++ - } else { - nodeid := cid.Next() - b.addCell(&cell, nodeid) - b.addEdge(int(pgno), nodeid) - } - - } - node.numBitmaps = numBitmaps - } - b.addNode(node) - if parent != 0 { - b.addEdge(int(parent), int(pgno)) - } - return nil - }) - if err != nil { - return errors.Wrapf(err, "walking %s", name.(string)) - } - } - return nil -} - -type cellID struct { - id int -} - -func (c *cellID) Next() int { - c.id++ - return c.id -} - -type vizNode struct { - name string - pgno uint32 - typ string - cellN int - numBitmaps int -} - -// builder wraps an io.Writer and understands how to compose DOT formatted elements. -type builder struct { - io.Writer -} - -// start generates a title and initial node in DOT format. -func (b *builder) start() { - graphname := "unnamed" - fmt.Fprintln(b, `digraph "`+graphname+`" {`) - fmt.Fprintln(b, `node [style=filled fillcolor="#f8f8f8"]`) -} - -// finish closes the opening curly bracket in the constructed DOT buffer. -func (b *builder) finish() { - fmt.Fprintln(b, "}") -} - -// addNode generates a graph node in DOT format. -func (b *builder) addNode(node *vizNode) { - label := fmt.Sprintf("%s %s", node.name, node.typ) - if node.typ != "bitmap" { - label = label + fmt.Sprintf(" N=%d", node.cellN) - } - if node.numBitmaps > 0 { - label = label + fmt.Sprintf(" bitMapCells=%d", node.numBitmaps) - } - - // Create DOT attribute for node. - attr := fmt.Sprintf(`label="%s" id="node%d" shape="rectangle"`, - label, node.pgno) - - fmt.Fprintf(b, "N%d [%s]\n", node.pgno, attr) -} - -// addEdge generates a graph edge in DOT format. -func (b *builder) addEdge(from, to int) { - fmt.Fprintf(b, "N%d -> N%d []\n", from, to) -} - -func (b *builder) addCell(cell *leafCell, id int) { - label := fmt.Sprintf(`k%d type:%s elemn:%d bitn:%d`, cell.Key, cell.Type, cell.ElemN, cell.BitN) - - fmt.Fprintf(b, `N%d [label="%s" id="node%d" shape="rectangle"]`, id, label, id) -}