mirror of
https://github.com/bluenviron/mediamtx
synced 2024-12-12 01:35:02 +00:00
125 lines
2.3 KiB
Go
125 lines
2.3 KiB
Go
package record
|
|
|
|
import (
|
|
"context"
|
|
"io/fs"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/bluenviron/mediamtx/internal/conf"
|
|
"github.com/bluenviron/mediamtx/internal/logger"
|
|
)
|
|
|
|
var timeNow = time.Now
|
|
|
|
// CleanerEntry is a cleaner entry.
|
|
type CleanerEntry struct {
|
|
Path string
|
|
Format conf.RecordFormat
|
|
DeleteAfter time.Duration
|
|
}
|
|
|
|
// Cleaner removes expired recording segments from disk.
|
|
type Cleaner struct {
|
|
Entries []CleanerEntry
|
|
Parent logger.Writer
|
|
|
|
ctx context.Context
|
|
ctxCancel func()
|
|
|
|
done chan struct{}
|
|
}
|
|
|
|
// Initialize initializes a Cleaner.
|
|
func (c *Cleaner) Initialize() {
|
|
c.ctx, c.ctxCancel = context.WithCancel(context.Background())
|
|
c.done = make(chan struct{})
|
|
|
|
go c.run()
|
|
}
|
|
|
|
// Close closes the Cleaner.
|
|
func (c *Cleaner) Close() {
|
|
c.ctxCancel()
|
|
<-c.done
|
|
}
|
|
|
|
// Log implements logger.Writer.
|
|
func (c *Cleaner) Log(level logger.Level, format string, args ...interface{}) {
|
|
c.Parent.Log(level, "[record cleaner]"+format, args...)
|
|
}
|
|
|
|
func (c *Cleaner) run() {
|
|
defer close(c.done)
|
|
|
|
interval := 30 * 60 * time.Second
|
|
for _, e := range c.Entries {
|
|
if interval > (e.DeleteAfter / 2) {
|
|
interval = e.DeleteAfter / 2
|
|
}
|
|
}
|
|
|
|
c.doRun() //nolint:errcheck
|
|
|
|
for {
|
|
select {
|
|
case <-time.After(interval):
|
|
c.doRun()
|
|
|
|
case <-c.ctx.Done():
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func (c *Cleaner) doRun() {
|
|
for _, e := range c.Entries {
|
|
c.doRunEntry(&e) //nolint:errcheck
|
|
}
|
|
}
|
|
|
|
func (c *Cleaner) doRunEntry(e *CleanerEntry) error {
|
|
entryPath := PathAddExtension(e.Path, e.Format)
|
|
|
|
// we have to convert to absolute paths
|
|
// otherwise, entryPath and fpath inside Walk() won't have common elements
|
|
entryPath, _ = filepath.Abs(entryPath)
|
|
|
|
commonPath := CommonPath(entryPath)
|
|
now := timeNow()
|
|
|
|
filepath.Walk(commonPath, func(fpath string, info fs.FileInfo, err error) error { //nolint:errcheck
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if !info.IsDir() {
|
|
var pa Path
|
|
ok := pa.Decode(entryPath, fpath)
|
|
if ok {
|
|
if now.Sub(pa.Start) > e.DeleteAfter {
|
|
c.Log(logger.Debug, "removing %s", fpath)
|
|
os.Remove(fpath)
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
filepath.Walk(commonPath, func(fpath string, info fs.FileInfo, err error) error { //nolint:errcheck
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if info.IsDir() {
|
|
os.Remove(fpath)
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
return nil
|
|
}
|