afa09d62c88148514522c9254c46ed41cdc1eb69 — Simon Ser 5 months ago 1863c38
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 @@ import (
 	"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 @@ func generateKey(n *drmtree.Node) (string, error) {
 	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 @@ func store(n *drmtree.Node) (string, error) {
 	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 @@ func load(k string) (*drmtree.Node, error) {
 	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 @@ func walk(fn func(k string, n *drmtree.Node) error) error {
 		}
 		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 @@ import (
 	"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 @@ func badRequest(c echo.Context, msg string, err error) error {
 	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 loadPCIIDs() (vendors map[uint16]string, devices map[uint32]string, err err
 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 @@ func New() *echo.Echo {
 
 		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 @@ func New() *echo.Echo {
 			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 @@ func New() *echo.Echo {
 			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 @@ func New() *echo.Echo {
 
 		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 @@ func New() *echo.Echo {
 		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 @@ import (
 	"io/ioutil"
 	"os"
 	"path/filepath"
+
+	"git.sr.ht/~emersion/drmdb/database"
 )
 
 const licenseFile = "LICENSE"


@@ 49,13 51,13 @@ func writeSnapshot(w io.Writer) error {
 		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
+}