Config: Use mutex when resolving the path of external binaries

Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
Michael Mayer 2022-10-12 18:39:30 +02:00
parent 9a3015a818
commit 38722e72c8
5 changed files with 29 additions and 19 deletions

View file

@ -4,7 +4,7 @@ import "github.com/photoprism/photoprism/internal/ffmpeg"
// FFmpegBin returns the ffmpeg executable file name.
func (c *Config) FFmpegBin() string {
return findExecutable(c.options.FFmpegBin, "ffmpeg")
return findBin(c.options.FFmpegBin, "ffmpeg")
}
// FFmpegEnabled checks if FFmpeg is enabled for video transcoding.

View file

@ -8,40 +8,50 @@ import (
"os/user"
"path/filepath"
"runtime"
"sync"
"github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/fs"
)
// binPaths stores known executable paths.
var binPaths = make(map[string]string, 8)
var tempPath = ""
var (
binPaths = make(map[string]string, 8)
binMu = sync.RWMutex{}
tempPath = ""
)
// findExecutable searches binaries by their name.
func findExecutable(configBin, defaultBin string) (binPath string) {
// Cached?
// findBin resolves the absolute file path of external binaries.
func findBin(configBin, defaultBin string) (binPath string) {
cacheKey := defaultBin + configBin
if cached, ok := binPaths[cacheKey]; ok {
binMu.RLock()
cached, found := binPaths[cacheKey]
binMu.RUnlock()
// Already found?
if found {
return cached
}
// Default if config value is empty.
// Default binary name?
if configBin == "" {
binPath = defaultBin
} else {
binPath = configBin
}
// Search.
// Search for binary.
if path, err := exec.LookPath(binPath); err == nil {
binPath = path
}
// Exists?
// Found?
if !fs.FileExists(binPath) {
binPath = ""
} else {
binMu.Lock()
binPaths[cacheKey] = binPath
binMu.Unlock()
}
return binPath
@ -481,17 +491,17 @@ func (c *Config) TestdataPath() string {
// MysqlBin returns the mysql executable file name.
func (c *Config) MysqlBin() string {
return findExecutable("", "mysql")
return findBin("", "mysql")
}
// MysqldumpBin returns the mysqldump executable file name.
func (c *Config) MysqldumpBin() string {
return findExecutable("", "mysqldump")
return findBin("", "mysqldump")
}
// SqliteBin returns the sqlite executable file name.
func (c *Config) SqliteBin() string {
return findExecutable("", "sqlite3")
return findBin("", "sqlite3")
}
// AlbumsPath returns the storage path for album YAML files.

View file

@ -10,7 +10,7 @@ import (
)
func TestConfig_FindExecutable(t *testing.T) {
assert.Equal(t, "", findExecutable("yyy", "xxx"))
assert.Equal(t, "", findBin("yyy", "xxx"))
}
func TestConfig_SidecarPath(t *testing.T) {

View file

@ -7,7 +7,7 @@ func (c *Config) ExifBruteForce() bool {
// ExifToolBin returns the exiftool executable file name.
func (c *Config) ExifToolBin() string {
return findExecutable(c.options.ExifToolBin, "exiftool")
return findBin(c.options.ExifToolBin, "exiftool")
}
// ExifToolJson checks if creating JSON metadata sidecar files with Exiftool is enabled.

View file

@ -18,7 +18,7 @@ func (c *Config) RawPresets() bool {
// DarktableBin returns the darktable-cli executable file name.
func (c *Config) DarktableBin() string {
return findExecutable(c.options.DarktableBin, "darktable-cli")
return findBin(c.options.DarktableBin, "darktable-cli")
}
// DarktableBlacklist returns the darktable file extension blacklist.
@ -73,7 +73,7 @@ func (c *Config) DarktableEnabled() bool {
// RawtherapeeBin returns the rawtherapee-cli executable file name.
func (c *Config) RawtherapeeBin() string {
return findExecutable(c.options.RawtherapeeBin, "rawtherapee-cli")
return findBin(c.options.RawtherapeeBin, "rawtherapee-cli")
}
// RawtherapeeBlacklist returns the RawTherapee file extension blacklist.
@ -93,7 +93,7 @@ func (c *Config) SipsEnabled() bool {
// SipsBin returns the SIPS executable file name.
func (c *Config) SipsBin() string {
return findExecutable(c.options.SipsBin, "sips")
return findBin(c.options.SipsBin, "sips")
}
// SipsBlacklist returns the Sips file extension blacklist.
@ -103,7 +103,7 @@ func (c *Config) SipsBlacklist() string {
// HeifConvertBin returns the heif-convert executable file name.
func (c *Config) HeifConvertBin() string {
return findExecutable(c.options.HeifConvertBin, "heif-convert")
return findBin(c.options.HeifConvertBin, "heif-convert")
}
// HeifConvertEnabled checks if heif-convert is enabled for HEIF conversion.