Ignite/utilities/frameserver/pool.go

105 lines
2.2 KiB
Go

package frameserver
import (
"git.gammaspectra.live/S.O.N.G/Ignite/frame"
"os"
"path"
"runtime"
"sync"
)
// Pool automatically grows and shrinks as-needed based on how many frame requests come in.
type Pool struct {
cachedFrameSeekTable []int64
seekTableLock sync.RWMutex
sourcePath string
pool sync.Pool
}
func NewPool(sourcePath string, cachedFrameSeekTable []int64) *Pool {
p := &Pool{
sourcePath: sourcePath,
cachedFrameSeekTable: cachedFrameSeekTable,
}
p.pool.New = func() any {
if f, err := os.Open(p.sourcePath); err != nil {
return nil
} else {
p.seekTableLock.RLock()
defer p.seekTableLock.RUnlock()
if path.Ext(p.sourcePath) == ".xz" {
if s := NewXZCompressed(f, p.cachedFrameSeekTable); s != nil {
runtime.SetFinalizer(s, func(s *FrameServer) {
f.Close()
})
return s
} else {
return nil
}
} else {
if s := New(f, p.cachedFrameSeekTable); s != nil {
runtime.SetFinalizer(s, func(s *FrameServer) {
f.Close()
})
return s
} else {
return nil
}
}
}
}
return p
}
func (p *Pool) getServer() *FrameServer {
if a := p.pool.Get(); a == nil {
return nil
} else {
return a.(*FrameServer)
}
}
func (p *Pool) GetFrameSeekTable() []int64 {
p.seekTableLock.RLock()
defer p.seekTableLock.RUnlock()
return p.cachedFrameSeekTable
}
func (p *Pool) putServer(s *FrameServer) {
if func() bool {
p.seekTableLock.RLock()
defer p.seekTableLock.RUnlock()
return len(p.cachedFrameSeekTable) < len(s.GetFrameSeekTable())
}() {
//cache longer table
p.seekTableLock.Lock()
defer p.seekTableLock.Unlock()
//avoid races overwriting things
if len(p.cachedFrameSeekTable) < len(s.GetFrameSeekTable()) {
p.cachedFrameSeekTable = s.GetFrameSeekTable()
}
}
p.pool.Put(s)
}
func (p *Pool) GetAllFrames() *frame.Stream {
if s := p.getServer(); s == nil {
return nil
} else {
defer p.putServer(s)
return s.GetAllFramesLock()
}
}
func (p *Pool) GetFrames(startFrameNumber, endFrameNumber int) *frame.Stream {
if s := p.getServer(); s == nil {
return nil
} else {
defer p.putServer(s)
return s.GetFramesLock(startFrameNumber, endFrameNumber)
}
}