Add implementations for protocoldb, yet untested.
build Details

This commit is contained in:
Marcel M. Otte 2023-04-13 11:27:03 +02:00
parent dd6e9158ca
commit 5906ee681a
1 changed files with 87 additions and 12 deletions

View File

@ -4,34 +4,50 @@ import (
"fmt" "fmt"
"io/fs" "io/fs"
"os" "os"
"path"
"path/filepath" "path/filepath"
"strings"
"gitea.mmo.to/ProtocolPacketForger/ppf/protocol" "gitea.mmo.to/ProtocolPacketForger/ppf/protocol"
"gitea.mmo.to/ProtocolPacketForger/ppf/protocolctl" "gitea.mmo.to/ProtocolPacketForger/ppf/protocolctl"
) )
// PPFDatabases is a list of all databases, with the most simple interface
type PPFDatabases struct { type PPFDatabases struct {
Databases []ProtocolDatabaseProvider Databases []ProtocolDatabaseProvider
} }
// ProtocolDatabaseProvider is a simple protocol database interface, which only provides open/close and retrieving the contents
type ProtocolDatabaseProvider interface { type ProtocolDatabaseProvider interface {
// Open opens a new database
Open(path string) error Open(path string) error
// Close closes a database (only internal flag set)
Close() error Close() error
Protocols() map[string]protocol.DOPMeta // Protocols returns the content of the database as map, an error if the first read of the database failed
Protocols() (map[string]protocol.DOPMeta, error)
} }
// ProtocolDatabaseManager is a complex protocol database interface, which allows adding, updating and refreshing of the content
type ProtocolDatabaseManager interface { type ProtocolDatabaseManager interface {
Add(prot *protocol.ProtocolStructure, path string) Add(prot *protocol.ProtocolStructure) error
Update(prot *protocol.ProtocolStructure, path string) AddFile(path string) error
Update(prot *protocol.ProtocolStructure) error
UpdateFile(path string) error
// no remove. // no remove.
UpdateDatabase() error // scans for new protocols UpdateDatabase() error // scans for new protocols
} }
// DatabaseEntry is a single entry in the file database, additionally to the meta data the path is required
type DatabaseEntry struct { type DatabaseEntry struct {
Path string Path string
Protocol protocol.DOPMeta Protocol protocol.DOPMeta
} }
// Get a full protocol from a database entry
func (de *DatabaseEntry) Get() (*protocol.ProtocolStructure, error) {
return protocolctl.LoadNew(de.Path)
}
// FileDatabase implements ProtocolDatabaseProvider and ProtocolDatabaseManager // FileDatabase implements ProtocolDatabaseProvider and ProtocolDatabaseManager
type FileDatabase struct { type FileDatabase struct {
Path string Path string
@ -39,11 +55,14 @@ type FileDatabase struct {
closed bool closed bool
} }
// FileDatabaseFromGitRemote implements retrieving the latest stuff from an external git remote additionally to the FileDatabase functionality
// TODO
type FileDatabaseFromGitRemote struct { type FileDatabaseFromGitRemote struct {
FileDatabase FileDatabase
RemoteGitRepository string RemoteGitRepository string
} }
// Open the database
func (fd *FileDatabase) Open(path string) error { func (fd *FileDatabase) Open(path string) error {
fileinfo, err := os.Stat(path) fileinfo, err := os.Stat(path)
if err == os.ErrNotExist { if err == os.ErrNotExist {
@ -57,6 +76,7 @@ func (fd *FileDatabase) Open(path string) error {
return nil return nil
} }
// Close the database and free the data
func (fd *FileDatabase) Close() error { func (fd *FileDatabase) Close() error {
for k := range fd.protocols { for k := range fd.protocols {
delete(fd.protocols, k) delete(fd.protocols, k)
@ -65,30 +85,85 @@ func (fd *FileDatabase) Close() error {
return nil return nil
} }
func (fd *FileDatabase) Protocols() map[string]DatabaseEntry { // Protocols returns the map of protocols or an error if the first read failed
if !fd.closed { func (fd *FileDatabase) Protocols() (map[string]DatabaseEntry, error) {
if !fd.closed && len(fd.protocols) == 0 {
fd.protocols = map[string]DatabaseEntry{} fd.protocols = map[string]DatabaseEntry{}
// recurse recursively through the path // recurse recursively through the path
filepath.Walk(fd.Path, func(path string, info fs.FileInfo, err error) error { err := filepath.Walk(fd.Path, func(path string, info fs.FileInfo, err error) error {
if !info.IsDir() { if !info.IsDir() {
prot, err := protocolctl.LoadNew(path) prot, err := protocolctl.LoadNew(path)
if err != nil { if err == nil {
// add to map // add to map
fd.protocols[prot.Metadata.Name] = DatabaseEntry{path, prot.Metadata} fd.protocols[prot.Metadata.Name] = DatabaseEntry{path, prot.Metadata}
} }
} }
return nil return nil
}) })
if err != nil {
return nil, err
}
} }
return fd.protocols return fd.protocols, nil
} }
func (fd *FileDatabase) Add(prot *protocol.ProtocolStructure, path string) { // Add puts a new protocol into the path of the file database
func (fd *FileDatabase) Add(prot *protocol.ProtocolStructure) error {
p := path.Join(fd.Path, prot.Metadata.Name, ".protocoljson")
err := protocolctl.Save(prot, p)
if err == nil {
fd.protocols[prot.Metadata.Name] = DatabaseEntry{p, prot.Metadata}
}
return err
} }
func (fd *FileDatabase) Update(prot *protocol.ProtocolStructure, path string) {
// AddFile copies a external protocoljson file into the database directory and updates the internal data
func (fd *FileDatabase) AddFile(p string) error {
prot, err := protocolctl.LoadNew(p)
if err == nil {
if !strings.HasPrefix(p, fd.Path) {
// add it to the database if not existing there
fd.Add(prot)
}
p = path.Join(fd.Path, prot.Metadata.Name, ".protocoljson")
fd.protocols[prot.Metadata.Name] = DatabaseEntry{p, prot.Metadata}
}
return err
} }
// Update updates an existing entry through saving the contents of the protocol to the file, or just adding it anew
func (fd *FileDatabase) Update(prot *protocol.ProtocolStructure) error {
if v, ok := fd.protocols[prot.Metadata.Name]; ok {
v.Protocol = prot.Metadata
return protocolctl.Save(prot, v.Path)
}
return fd.Add(prot)
}
// UpdateFile simply adds a file if it is outside the database, or updates the internal storage with the contents of the file
func (fd *FileDatabase) UpdateFile(p string) error {
if !strings.HasPrefix(p, fd.Path) {
return fd.AddFile(p)
}
prot, err := protocolctl.LoadNew(p)
if err == nil {
fd.protocols[prot.Metadata.Name] = DatabaseEntry{p, prot.Metadata}
}
return err
}
// UpdateDatabase just rereads all files
func (fd *FileDatabase) UpdateDatabase() error { func (fd *FileDatabase) UpdateDatabase() error {
// recurse recursively through the path
err := filepath.Walk(fd.Path, func(path string, info fs.FileInfo, err error) error {
if !info.IsDir() {
prot, err := protocolctl.LoadNew(path)
if err == nil {
// add to map
fd.protocols[prot.Metadata.Name] = DatabaseEntry{path, prot.Metadata}
}
}
return nil
})
return err
} }