afa09d62c88148514522c9254c46ed41cdc1eb69 — Simon Ser 2 months ago 1863c38 master
Move database functions to a separate package
4 files changed, 128 insertions(+), 112 deletions(-)

R db.go => database/db.go
M server.go
M snapshot.go
A walk.go
R db.go => database/db.go +15 -11
@@ 1,4 1,4 @@-package drmdb
+ package database
  
  import (
  	"bytes"


@@ 14,9 14,9 @@ "git.sr.ht/~emersion/drmdb/drmtree"
  )
  
- const dbDir = "db"
+ const Dir = "db"
  
- var errStop = fmt.Errorf("drmdb: stop walking")
+ var ErrStop = fmt.Errorf("drmdb: stop walking")
  
  func generateKey(n *drmtree.Node) (string, error) {
  	if n.Driver == nil || n.Device == nil {


@@ 56,13 56,17 @@ return hex.EncodeToString(sum[:])[:12], nil
  }
  
- func store(n *drmtree.Node) (string, error) {
+ func Init() error {
+ 	return os.MkdirAll(Dir, 0755)
+ }
+ 
+ func Store(n *drmtree.Node) (string, error) {
  	k, err := generateKey(n)
  	if err != nil {
  		return "", err
  	}
  
- 	p := filepath.Join(dbDir, k+".json")
+ 	p := filepath.Join(Dir, k+".json")
  	f, err := os.OpenFile(p, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666)
  	if err != nil {
  		if os.IsExist(err) {


@@ 79,8 83,8 @@ return k, f.Close()
  }
  
- func load(k string) (*drmtree.Node, error) {
- 	p := filepath.Join(dbDir, k + ".json")
+ func Load(k string) (*drmtree.Node, error) {
+ 	p := filepath.Join(Dir, k + ".json")
  	f, err := os.Open(p)
  	if err != nil {
  		return nil, err


@@ 95,8 99,8 @@ return &n, f.Close()
  }
  
- func walk(fn func(k string, n *drmtree.Node) error) error {
- 	files, err := ioutil.ReadDir(dbDir)
+ func Walk(fn func(k string, n *drmtree.Node) error) error {
+ 	files, err := ioutil.ReadDir(Dir)
  	if err != nil {
  		return err
  	}


@@ 107,12 111,12 @@ }
  		k := strings.TrimSuffix(fi.Name(), ".json")
  
- 		n, err := load(k)
+ 		n, err := Load(k)
  		if err != nil {
  			return err
  		}
  
- 		if err := fn(k, n); err == errStop {
+ 		if err := fn(k, n); err == ErrStop {
  			return nil
  		} else if err != nil {
  			return err

M server.go => server.go +8 -99
@@ 10,12 10,12 @@ "strconv"
  	"strings"
  
+ 	"git.sr.ht/~emersion/drmdb/database"
  	"git.sr.ht/~emersion/drmdb/drmtree"
  	"git.sr.ht/~emersion/drmdb/treefmt"
  	"git.sr.ht/~emersion/go-drm"
  	"git.sr.ht/~emersion/go-hwids"
  	"github.com/labstack/echo/v4"
- 	"github.com/mcuadros/go-version"
  )
  
  func badRequest(c echo.Context, msg string, err error) error {


@@ 25,97 25,6 @@ return c.String(http.StatusBadRequest, "Error: "+msg+"\n")
  }
  
- func walkProps(props drmtree.PropertyMap, obj drm.AnyID, f func(drm.AnyID, string, *drmtree.Property) error) error {
- 	for name, prop := range props {
- 		if err := f(obj, name, &prop); err != nil {
- 			return err
- 		}
- 	}
- 	return nil
- }
- 
- func walkNodeProps(n *drmtree.Node, f func(drm.AnyID, string, *drmtree.Property) error) error {
- 	for _, conn := range n.Connectors {
- 		if err := walkProps(conn.Properties, conn.ID, f); err != nil {
- 			return err
- 		}
- 	}
- 	for _, crtc := range n.CRTCs {
- 		if err := walkProps(crtc.Properties, crtc.ID, f); err != nil {
- 			return err
- 		}
- 	}
- 	for _, plane := range n.Planes {
- 		if err := walkProps(plane.Properties, plane.ID, f); err != nil {
- 			return err
- 		}
- 	}
- 	return nil
- }
- 
- func driverLess(a *drmtree.Driver, b *drmtree.Driver) bool {
- 	if a.Version.Less(&b.Version) {
- 		return true
- 	}
- 	// Linux is the upstream
- 	if b.Kernel.SysName == "Linux" && a.Kernel.SysName != "Linux" {
- 		return true
- 	}
- 	return version.Compare(a.Kernel.Release, b.Kernel.Release, "<")
- }
- 
- type walkLatestField int
- 
- const (
- 	walkLatestDriver walkLatestField = iota
- 	walkLatestDevice
- )
- 
- func walkLatest(f walkLatestField, fn func(k string, n *drmtree.Node) error) error {
- 	type node struct {
- 		k string
- 		n *drmtree.Node
- 	}
- 
- 	latest := make(map[string]node)
- 	err := walk(func(k string, n *drmtree.Node) error {
- 		var latestKey string
- 		switch f {
- 		case walkLatestDriver:
- 			latestKey = n.Driver.Name
- 		case walkLatestDevice:
- 			latestKey = n.Device.BusID()
- 		}
- 		if latestKey == "" {
- 			return nil
- 		}
- 
- 		other, ok := latest[latestKey]
- 		if ok && driverLess(n.Driver, other.n.Driver) {
- 			return nil
- 		}
- 		latest[latestKey] = node{k, n}
- 		return nil
- 	})
- 	if err != nil {
- 		return err
- 	}
- 
- 	keys := make([]string, 0, len(latest))
- 	for k := range latest {
- 		keys = append(keys, k)
- 	}
- 	sort.Strings(keys)
- 
- 	for _, k := range keys {
- 		n := latest[k]
- 		if err := fn(n.k, n.n); err != nil {
- 			return err
- 		}
- 	}
- 	return nil
- }
- 
  func loadPCIIDs() (vendors map[uint16]string, devices map[uint32]string, err error) {
  	vendors = make(map[uint16]string)
  	devices = make(map[uint32]string)


@@ 149,8 58,8 @@ func New() *echo.Echo {
  	e := echo.New()
  
- 	if err := os.MkdirAll(dbDir, 0755); err != nil {
- 		e.Logger.Fatal("Failed to create DB dir:", err)
+ 	if err := database.Init(); err != nil {
+ 		e.Logger.Fatal("Failed to initialize database:", err)
  	}
  
  	var err error


@@ 181,7 90,7 @@   		success := false
  		for name, n := range nodes {
- 			if key, err := store(n); err != nil {
+ 			if key, err := database.Store(n); err != nil {
  				fmt.Fprintf(c.Response(), "%s: error: %v\n", name, err)
  			} else {
  				u := "https://" + c.Request().Host + "/devices/" + key


@@ 272,7 181,7 @@ raw = true
  		}
  
- 		n, err := load(key)
+ 		n, err := database.Load(key)
  		if err != nil {
  			if os.IsNotExist(err) {
  				return c.String(http.StatusNotFound, "no such device")


@@ 284,7 193,7 @@ return c.JSON(http.StatusOK, n)
  		} else {
  			var altDevices []altDeviceData
- 			err := walk(func(k string, alt *drmtree.Node) error {
+ 			err := database.Walk(func(k string, alt *drmtree.Node) error {
  				if k == key {
  					return nil
  				}


@@ 363,7 272,7 @@   		drivers := make(map[string]struct{})
  		props := make(map[string]propertyData)
- 		err := walk(func(k string, n *drmtree.Node) error {
+ 		err := database.Walk(func(k string, n *drmtree.Node) error {
  			drv := n.Driver.Name
  			drivers[drv] = struct{}{}
  


@@ 402,7 311,7 @@ var property drmtree.Property
  
  		drivers := make(map[string]bool)
- 		err := walk(func(k string, n *drmtree.Node) error {
+ 		err := database.Walk(func(k string, n *drmtree.Node) error {
  			drivers[n.Driver.Name] = false
  
  			return walkNodeProps(n, func(obj drm.AnyID, name string, p *drmtree.Property) error {

M snapshot.go => snapshot.go +4 -2
@@ 7,6 7,8 @@ "io/ioutil"
  	"os"
  	"path/filepath"
+ 
+ 	"git.sr.ht/~emersion/drmdb/database"
  )
  
  const licenseFile = "LICENSE"


@@ 49,13 51,13 @@ return err
  	}
  
- 	files, err := ioutil.ReadDir(dbDir)
+ 	files, err := ioutil.ReadDir(database.Dir)
  	if err != nil {
  		return err
  	}
  
  	for _, fi := range files {
- 		p := filepath.Join(dbDir, fi.Name())
+ 		p := filepath.Join(database.Dir, fi.Name())
  		if err := writeSnapshotFile(tw, p, fi); err != nil {
  			return err
  		}

A walk.go => walk.go +101 -0
@@ 0,0 1,101 @@
+ package drmdb
+ 
+ import (
+ 	"sort"
+ 
+ 	"git.sr.ht/~emersion/drmdb/database"
+ 	"git.sr.ht/~emersion/drmdb/drmtree"
+ 	"git.sr.ht/~emersion/go-drm"
+ 	"github.com/mcuadros/go-version"
+ )
+ 
+ func walkProps(props drmtree.PropertyMap, obj drm.AnyID, f func(drm.AnyID, string, *drmtree.Property) error) error {
+ 	for name, prop := range props {
+ 		if err := f(obj, name, &prop); err != nil {
+ 			return err
+ 		}
+ 	}
+ 	return nil
+ }
+ 
+ func walkNodeProps(n *drmtree.Node, f func(drm.AnyID, string, *drmtree.Property) error) error {
+ 	for _, conn := range n.Connectors {
+ 		if err := walkProps(conn.Properties, conn.ID, f); err != nil {
+ 			return err
+ 		}
+ 	}
+ 	for _, crtc := range n.CRTCs {
+ 		if err := walkProps(crtc.Properties, crtc.ID, f); err != nil {
+ 			return err
+ 		}
+ 	}
+ 	for _, plane := range n.Planes {
+ 		if err := walkProps(plane.Properties, plane.ID, f); err != nil {
+ 			return err
+ 		}
+ 	}
+ 	return nil
+ }
+ 
+ func driverLess(a *drmtree.Driver, b *drmtree.Driver) bool {
+ 	if a.Version.Less(&b.Version) {
+ 		return true
+ 	}
+ 	// Linux is the upstream
+ 	if b.Kernel.SysName == "Linux" && a.Kernel.SysName != "Linux" {
+ 		return true
+ 	}
+ 	return version.Compare(a.Kernel.Release, b.Kernel.Release, "<")
+ }
+ 
+ type walkLatestField int
+ 
+ const (
+ 	walkLatestDriver walkLatestField = iota
+ 	walkLatestDevice
+ )
+ 
+ func walkLatest(f walkLatestField, fn func(k string, n *drmtree.Node) error) error {
+ 	type node struct {
+ 		k string
+ 		n *drmtree.Node
+ 	}
+ 
+ 	latest := make(map[string]node)
+ 	err := database.Walk(func(k string, n *drmtree.Node) error {
+ 		var latestKey string
+ 		switch f {
+ 		case walkLatestDriver:
+ 			latestKey = n.Driver.Name
+ 		case walkLatestDevice:
+ 			latestKey = n.Device.BusID()
+ 		}
+ 		if latestKey == "" {
+ 			return nil
+ 		}
+ 
+ 		other, ok := latest[latestKey]
+ 		if ok && driverLess(n.Driver, other.n.Driver) {
+ 			return nil
+ 		}
+ 		latest[latestKey] = node{k, n}
+ 		return nil
+ 	})
+ 	if err != nil {
+ 		return err
+ 	}
+ 
+ 	keys := make([]string, 0, len(latest))
+ 	for k := range latest {
+ 		keys = append(keys, k)
+ 	}
+ 	sort.Strings(keys)
+ 
+ 	for _, k := range keys {
+ 		n := latest[k]
+ 		if err := fn(n.k, n.n); err != nil {
+ 			return err
+ 		}
+ 	}
+ 	return nil
+ }