Use cmap for infos

This commit is contained in:
Zoe Roux 2024-02-19 00:47:25 +01:00
parent 2afed432f7
commit f54a876636
5 changed files with 53 additions and 26 deletions

View File

@ -176,19 +176,20 @@ func (h *Handler) GetInfo(c echo.Context) error {
return err return err
} }
route := GetRoute(c)
sha, err := src.GetHash(path) sha, err := src.GetHash(path)
if err != nil { if err != nil {
return err return err
} }
ret, err := src.GetInfo(path) ret, err := src.GetInfo(path, sha, route)
if err != nil { if err != nil {
return err return err
} }
// Run extractors to have them in cache // Run extractors to have them in cache
src.Extract(ret.Path, sha) src.Extract(ret.Path, sha, route)
go h.thumbnails.ExtractThumbnail( go h.thumbnails.ExtractThumbnail(
ret.Path, ret.Path,
fmt.Sprintf("%s/thumbnails.png", c.Request().Header.Get("X-Route")), fmt.Sprintf("%s/thumbnails.png", route),
) )
return c.JSON(http.StatusOK, ret) return c.JSON(http.StatusOK, ret)
} }
@ -208,11 +209,12 @@ func (h *Handler) GetAttachment(c echo.Context) error {
return err return err
} }
route := GetRoute(c)
sha, err := src.GetHash(path) sha, err := src.GetHash(path)
if err != nil { if err != nil {
return err return err
} }
wait, err := src.Extract(path, sha) wait, err := src.Extract(path, sha, route)
if err != nil { if err != nil {
return err return err
} }
@ -237,11 +239,12 @@ func (h *Handler) GetSubtitle(c echo.Context) error {
return err return err
} }
route := GetRoute(c)
sha, err := src.GetHash(path) sha, err := src.GetHash(path)
if err != nil { if err != nil {
return err return err
} }
wait, err := src.Extract(path, sha) wait, err := src.Extract(path, sha, route)
if err != nil { if err != nil {
return err return err
} }
@ -264,7 +267,7 @@ func (h *Handler) GetThumbnails(c echo.Context) error {
out, err := h.thumbnails.ExtractThumbnail( out, err := h.thumbnails.ExtractThumbnail(
path, path,
fmt.Sprintf("%s/thumbnails.png", c.Request().Header.Get("X-Route")), fmt.Sprintf("%s/thumbnails.png", GetRoute(c)),
) )
if err != nil { if err != nil {
return err return err
@ -287,7 +290,7 @@ func (h *Handler) GetThumbnailsVtt(c echo.Context) error {
out, err := h.thumbnails.ExtractThumbnail( out, err := h.thumbnails.ExtractThumbnail(
path, path,
fmt.Sprintf("%s/thumbnails.png", c.Request().Header.Get("X-Route")), fmt.Sprintf("%s/thumbnails.png", GetRoute(c)),
) )
if err != nil { if err != nil {
return err return err

View File

@ -48,6 +48,13 @@ func (m *CMap[K, V]) GetOrSet(key K, val V) (V, bool) {
return m.GetOrCreate(key, func() V { return val }) return m.GetOrCreate(key, func() V { return val })
} }
func (m *CMap[K, V]) Set(key K, val V) {
m.lock.Lock()
defer m.lock.Unlock()
m.data[key] = val
}
func (m *CMap[K, V]) Remove(key K) { func (m *CMap[K, V]) Remove(key K) {
m.lock.Lock() m.lock.Lock()
defer m.lock.Unlock() defer m.lock.Unlock()

View File

@ -8,7 +8,7 @@ import (
var extracted = NewCMap[string, <-chan struct{}]() var extracted = NewCMap[string, <-chan struct{}]()
func Extract(path string, sha string) (<-chan struct{}, error) { func Extract(path string, sha string, route string) (<-chan struct{}, error) {
ret := make(chan struct{}) ret := make(chan struct{})
existing, created := extracted.GetOrSet(sha, ret) existing, created := extracted.GetOrSet(sha, ret)
if !created { if !created {
@ -16,7 +16,7 @@ func Extract(path string, sha string) (<-chan struct{}, error) {
} }
go func() { go func() {
info, err := GetInfo(path) info, err := GetInfo(path, sha, route)
if err != nil { if err != nil {
extracted.Remove(sha) extracted.Remove(sha)
close(ret) close(ret)

View File

@ -1,8 +1,6 @@
package src package src
import ( import (
"crypto/sha1"
"encoding/hex"
"fmt" "fmt"
"path/filepath" "path/filepath"
"strconv" "strconv"
@ -12,6 +10,8 @@ import (
) )
type MediaInfo struct { type MediaInfo struct {
// closed if the mediainfo is ready for read. open otherwise
ready <-chan struct{}
// The sha1 of the video file. // The sha1 of the video file.
Sha string `json:"sha"` Sha string `json:"sha"`
/// The internal path of the video file. /// The internal path of the video file.
@ -173,7 +173,32 @@ var SubtitleExtensions = map[string]string{
"vtt": "vtt", "vtt": "vtt",
} }
func GetInfo(path string) (*MediaInfo, error) { var infos = NewCMap[string, *MediaInfo]()
func GetInfo(path string, sha string, route string) (*MediaInfo, error) {
var err error
ret, _ := infos.GetOrCreate(sha, func() *MediaInfo {
readyChan := make(chan struct{})
mi := &MediaInfo{
Sha: sha,
ready: readyChan,
}
go func() {
var val *MediaInfo
val, err = getInfo(path, route)
*mi = *val
mi.ready = readyChan
mi.Sha = sha
close(readyChan)
}()
return mi
})
<-ret.ready
return ret, err
}
func getInfo(path string, route string) (*MediaInfo, error) {
defer printExecTime("mediainfo for %s", path)() defer printExecTime("mediainfo for %s", path)()
mi, err := mediainfo.Open(path) mi, err := mediainfo.Open(path)
@ -182,17 +207,6 @@ func GetInfo(path string) (*MediaInfo, error) {
} }
defer mi.Close() defer mi.Close()
sha := mi.Parameter(mediainfo.StreamGeneral, 0, "UniqueID")
// Remove dummy values that some tools use.
if len(sha) <= 5 {
date := mi.Parameter(mediainfo.StreamGeneral, 0, "File_Modified_Date")
h := sha1.New()
h.Write([]byte(path))
h.Write([]byte(date))
sha = hex.EncodeToString(h.Sum(nil))
}
chapters_begin := ParseUint(mi.Parameter(mediainfo.StreamMenu, 0, "Chapters_Pos_Begin")) chapters_begin := ParseUint(mi.Parameter(mediainfo.StreamMenu, 0, "Chapters_Pos_Begin"))
chapters_end := ParseUint(mi.Parameter(mediainfo.StreamMenu, 0, "Chapters_Pos_End")) chapters_end := ParseUint(mi.Parameter(mediainfo.StreamMenu, 0, "Chapters_Pos_End"))
@ -204,7 +218,6 @@ func GetInfo(path string) (*MediaInfo, error) {
// fmt.Printf("%s", mi.Option("info_parameters", "")) // fmt.Printf("%s", mi.Option("info_parameters", ""))
ret := MediaInfo{ ret := MediaInfo{
Sha: sha,
Path: path, Path: path,
// Remove leading . // Remove leading .
Extension: filepath.Ext(path)[1:], Extension: filepath.Ext(path)[1:],
@ -248,7 +261,7 @@ func GetInfo(path string) (*MediaInfo, error) {
extension := OrNull(SubtitleExtensions[format]) extension := OrNull(SubtitleExtensions[format])
var link *string var link *string
if extension != nil { if extension != nil {
x := fmt.Sprintf("/video/%s/subtitle/%d.%s", sha, i, *extension) x := fmt.Sprintf("%s/subtitle/%d.%s", route, i, *extension)
link = &x link = &x
} }
return Subtitle{ return Subtitle{
@ -273,7 +286,7 @@ func GetInfo(path string) (*MediaInfo, error) {
Fonts: Map( Fonts: Map(
attachments, attachments,
func(font string, _ int) string { func(font string, _ int) string {
return fmt.Sprintf("/video/%s/attachment/%s", sha, font) return fmt.Sprintf("%s/attachment/%s", route, font)
}), }),
} }
if len(ret.Videos) > 0 { if len(ret.Videos) > 0 {

View File

@ -23,6 +23,10 @@ func GetPath(c echo.Context) (string, error) {
return key, nil return key, nil
} }
func GetRoute(c echo.Context) string {
return c.Request().Header.Get("X-Route")
}
func SanitizePath(path string) error { func SanitizePath(path string) error {
if strings.Contains(path, "/") || strings.Contains(path, "..") { if strings.Contains(path, "/") || strings.Contains(path, "..") {
return echo.NewHTTPError(http.StatusBadRequest, "Invalid parameter. Can't contains path delimiters or ..") return echo.NewHTTPError(http.StatusBadRequest, "Invalid parameter. Can't contains path delimiters or ..")