Full Mattermost server source with integrated Community Enterprise features. Includes vendor directory for offline/air-gapped builds. Structure: - enterprise-impl/: Enterprise feature implementations - enterprise-community/: Init files that register implementations - enterprise/: Bridge imports (community_imports.go) - vendor/: All dependencies for offline builds Build (online): go build ./cmd/mattermost Build (offline/air-gapped): go build -mod=vendor ./cmd/mattermost 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
139 lines
2.8 KiB
Go
139 lines
2.8 KiB
Go
// Package pool implements the reader pooling.
|
|
package pool
|
|
|
|
import (
|
|
"container/list"
|
|
"runtime"
|
|
"sort"
|
|
"sync"
|
|
|
|
"github.com/bodgit/sevenzip/internal/util"
|
|
)
|
|
|
|
// Pooler is the interface implemented by a pool.
|
|
type Pooler interface {
|
|
Get(offset int64) (util.SizeReadSeekCloser, bool)
|
|
Put(offset int64, rc util.SizeReadSeekCloser) (bool, error)
|
|
}
|
|
|
|
// Constructor is the function prototype used to instantiate a pool.
|
|
type Constructor func() (Pooler, error)
|
|
|
|
type noopPool struct{}
|
|
|
|
// NewNoopPool returns a Pooler that doesn't actually pool anything.
|
|
func NewNoopPool() (Pooler, error) {
|
|
return new(noopPool), nil
|
|
}
|
|
|
|
func (noopPool) Get(_ int64) (util.SizeReadSeekCloser, bool) {
|
|
return nil, false
|
|
}
|
|
|
|
func (noopPool) Put(_ int64, rc util.SizeReadSeekCloser) (bool, error) {
|
|
return false, rc.Close() //nolint:wrapcheck
|
|
}
|
|
|
|
type pool struct {
|
|
mutex sync.Mutex
|
|
size int
|
|
evictList *list.List
|
|
items map[int64]*list.Element
|
|
}
|
|
|
|
type entry struct {
|
|
key int64
|
|
value util.SizeReadSeekCloser
|
|
}
|
|
|
|
// NewPool returns a Pooler that uses a LRU strategy to maintain a fixed pool
|
|
// of util.SizeReadSeekCloser's keyed by their stream offset.
|
|
func NewPool() (Pooler, error) {
|
|
return &pool{
|
|
size: runtime.NumCPU(),
|
|
evictList: list.New(),
|
|
items: make(map[int64]*list.Element),
|
|
}, nil
|
|
}
|
|
|
|
func (p *pool) Get(offset int64) (util.SizeReadSeekCloser, bool) {
|
|
p.mutex.Lock()
|
|
defer p.mutex.Unlock()
|
|
|
|
if ent, ok := p.items[offset]; ok {
|
|
_ = p.removeElement(ent, false)
|
|
|
|
return ent.Value.(*entry).value, true //nolint:forcetypeassert
|
|
}
|
|
|
|
// Sort keys in descending order
|
|
keys := p.keys()
|
|
sort.Slice(keys, func(i, j int) bool { return keys[i] > keys[j] })
|
|
|
|
for _, k := range keys {
|
|
// First key less than offset is the closest
|
|
if k < offset {
|
|
ent := p.items[k]
|
|
_ = p.removeElement(ent, false)
|
|
|
|
return ent.Value.(*entry).value, true //nolint:forcetypeassert
|
|
}
|
|
}
|
|
|
|
return nil, false
|
|
}
|
|
|
|
func (p *pool) Put(offset int64, rc util.SizeReadSeekCloser) (bool, error) {
|
|
p.mutex.Lock()
|
|
defer p.mutex.Unlock()
|
|
|
|
if _, ok := p.items[offset]; ok {
|
|
return false, nil
|
|
}
|
|
|
|
ent := &entry{offset, rc}
|
|
entry := p.evictList.PushFront(ent)
|
|
p.items[offset] = entry
|
|
|
|
var err error
|
|
|
|
evict := p.evictList.Len() > p.size
|
|
if evict {
|
|
err = p.removeOldest()
|
|
}
|
|
|
|
return evict, err
|
|
}
|
|
|
|
func (p *pool) keys() []int64 {
|
|
keys := make([]int64, len(p.items))
|
|
i := 0
|
|
|
|
for ent := p.evictList.Back(); ent != nil; ent = ent.Prev() {
|
|
keys[i] = ent.Value.(*entry).key //nolint:forcetypeassert
|
|
i++
|
|
}
|
|
|
|
return keys
|
|
}
|
|
|
|
func (p *pool) removeOldest() error {
|
|
if ent := p.evictList.Back(); ent != nil {
|
|
return p.removeElement(ent, true)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p *pool) removeElement(e *list.Element, cb bool) error {
|
|
p.evictList.Remove(e)
|
|
kv := e.Value.(*entry) //nolint:forcetypeassert
|
|
delete(p.items, kv.key)
|
|
|
|
if cb {
|
|
return kv.value.Close() //nolint:wrapcheck
|
|
}
|
|
|
|
return nil
|
|
}
|