mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-06 12:33:51 +08:00
ab81464bd1
Add navigation and map matching providers with the vendored map service sources. Co-authored-by: Daniel Koepping <elkoled@gmail.com> Co-authored-by: Danny <dannyirwin31@yahoo.com> Co-authored-by: Prabhaav Pillai <prabhaav@msu.edu> Co-authored-by: dirwin31 <83434411+dirwin31@users.noreply.github.com>
236 lines
5.0 KiB
Go
236 lines
5.0 KiB
Go
package params
|
|
|
|
import (
|
|
"log/slog"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/gofrs/flock"
|
|
)
|
|
|
|
var (
|
|
ParamsPath string = "/data/params/d"
|
|
BasePath string = GetBasePath()
|
|
)
|
|
|
|
func GetBaseOpPath() string {
|
|
exists, err := Exists("/data/media/0")
|
|
if err != nil {
|
|
slog.Warn("could not check if /data/media/0 exists", "error", err)
|
|
}
|
|
if exists {
|
|
return "/data/media/0/osm"
|
|
} else {
|
|
return "."
|
|
}
|
|
}
|
|
|
|
// Params
|
|
var (
|
|
LAST_GPS_POSITION = ParamPath("LastGPSPosition")
|
|
MAPD_SETTINGS = ParamPath("MapdSettings")
|
|
)
|
|
|
|
// exists returns whether the given file or directory exists
|
|
func Exists(path string) (bool, error) {
|
|
_, err := os.Stat(path)
|
|
if err == nil {
|
|
return true, nil
|
|
}
|
|
if os.IsNotExist(err) {
|
|
return false, nil
|
|
}
|
|
return false, errors.Wrap(err, "could not check param file stats")
|
|
}
|
|
|
|
func GetBasePath() string {
|
|
exists, err := Exists("/data/media/0")
|
|
if err != nil {
|
|
slog.Warn("could not check if /data/media/0 exists", "error", err)
|
|
}
|
|
if exists {
|
|
return "/data/media/0/osm"
|
|
} else {
|
|
return "media/"
|
|
}
|
|
}
|
|
|
|
func EnsureParamDirectories() {
|
|
err := os.MkdirAll(ParamsPath, 0o775)
|
|
if err != nil {
|
|
slog.Warn("could not make params directory", "error", err, "directory", ParamsPath)
|
|
}
|
|
}
|
|
|
|
func ResetParams() {
|
|
}
|
|
|
|
func IsString(data []byte) bool {
|
|
for _, b := range data {
|
|
if (b < 32 || b > 126) && !(b == 9 || b == 13 || b == 10) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func GetParams() ([]string, error) {
|
|
basePath := ParamsPath
|
|
|
|
files, err := os.ReadDir(basePath)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read params directory")
|
|
}
|
|
|
|
paramFiles := []string{}
|
|
for _, file := range files {
|
|
name := file.Name()
|
|
if file.Type().IsRegular() && name[0] != '.' {
|
|
paramFiles = append(paramFiles, name)
|
|
}
|
|
}
|
|
sort.Strings(paramFiles)
|
|
|
|
return paramFiles, nil
|
|
}
|
|
|
|
func ParamPath(name string) string {
|
|
var basePath string
|
|
basePath = ParamsPath
|
|
return filepath.Join(basePath, name)
|
|
}
|
|
|
|
func GetParam(path string) ([]byte, error) {
|
|
return os.ReadFile(path)
|
|
}
|
|
|
|
func PutParam(path string, data []byte) error {
|
|
dir := filepath.Dir(path)
|
|
lock_dir := filepath.Dir(dir)
|
|
file, err := os.CreateTemp(dir, ".tmp_value_"+filepath.Base(path))
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not create temp param file")
|
|
}
|
|
tmpName := file.Name()
|
|
defer os.Remove(tmpName)
|
|
|
|
_, err = file.Write(data)
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not write data to temp param file")
|
|
}
|
|
|
|
err = file.Sync()
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not fsync temp param file")
|
|
}
|
|
|
|
fileLock := flock.New(filepath.Join(lock_dir, ".lock"))
|
|
|
|
retries := 0
|
|
for {
|
|
locked, err := fileLock.TryLock()
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not try locking param directory")
|
|
}
|
|
if locked {
|
|
break
|
|
}
|
|
retries += 1
|
|
if retries > 30 {
|
|
// try to force the lock to be removed
|
|
if err := os.Remove(filepath.Join(lock_dir, ".lock")); err != nil {
|
|
slog.Debug("failed to force delete params lock", "error", err)
|
|
}
|
|
}
|
|
if retries > 50 {
|
|
return errors.New("could not obtain lock")
|
|
}
|
|
// if we didn't obtain the lock let's try again after a short delay
|
|
time.Sleep(1 * time.Millisecond)
|
|
}
|
|
defer func() {
|
|
if err := fileLock.Unlock(); err != nil {
|
|
slog.Error("could not unlock params directory", "error", err)
|
|
}
|
|
}()
|
|
defer func() {
|
|
if err := os.Remove(filepath.Join(lock_dir, ".lock")); err != nil {
|
|
slog.Error("could not remove params lock file", "error", err)
|
|
}
|
|
}()
|
|
|
|
err = os.Rename(tmpName, path)
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not move temp param file to persistent location")
|
|
}
|
|
|
|
directory, err := os.Open(dir)
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not open params directory")
|
|
}
|
|
|
|
err = directory.Sync()
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not fsync params directory")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func RemoveParam(path string) error {
|
|
dir := filepath.Dir(path)
|
|
lock_dir := filepath.Dir(dir)
|
|
fileLock := flock.New(filepath.Join(lock_dir, ".lock"))
|
|
|
|
retries := 0
|
|
for {
|
|
locked, err := fileLock.TryLock()
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not try locking params directory")
|
|
}
|
|
if locked {
|
|
break
|
|
}
|
|
retries += 1
|
|
if retries > 30 {
|
|
// try to force the lock to be removed
|
|
if err := os.Remove(filepath.Join(lock_dir, ".lock")); err != nil {
|
|
slog.Debug("failed to force delete params lock", "error", err)
|
|
}
|
|
}
|
|
if retries > 50 {
|
|
return errors.New("could not obtain lock")
|
|
}
|
|
// if we didn't obtain the lock let's try again after a short delay
|
|
time.Sleep(1 * time.Millisecond)
|
|
}
|
|
defer func() {
|
|
if err := fileLock.Unlock(); err != nil {
|
|
slog.Error("could not unlock params directory", "error", err)
|
|
}
|
|
}()
|
|
defer func() {
|
|
if err := os.Remove(filepath.Join(lock_dir, ".lock")); err != nil {
|
|
slog.Error("could not remove params lock file", "error", err)
|
|
}
|
|
}()
|
|
|
|
os.Remove(path)
|
|
|
|
directory, err := os.Open(dir)
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not open params directory")
|
|
}
|
|
|
|
err = directory.Sync()
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not fsync params directory")
|
|
}
|
|
|
|
return nil
|
|
}
|