75 lines
1.5 KiB
Go
75 lines
1.5 KiB
Go
package filtering
|
|
|
|
import (
|
|
"fmt"
|
|
"sync/atomic"
|
|
|
|
"github.com/AdguardTeam/AdGuardHome/internal/filtering/rulelist"
|
|
"github.com/AdguardTeam/golibs/container"
|
|
"github.com/AdguardTeam/golibs/log"
|
|
)
|
|
|
|
// idGenerator generates filtering-list IDs in a way broadly compatible with the
|
|
// legacy approach of AdGuard Home.
|
|
//
|
|
// TODO(a.garipov): Get rid of this once we switch completely to the new
|
|
// rule-list architecture.
|
|
type idGenerator struct {
|
|
current *atomic.Int32
|
|
}
|
|
|
|
// newIDGenerator returns a new ID generator initialized with the given seed
|
|
// value.
|
|
func newIDGenerator(seed int32) (g *idGenerator) {
|
|
g = &idGenerator{
|
|
current: &atomic.Int32{},
|
|
}
|
|
|
|
g.current.Store(seed)
|
|
|
|
return g
|
|
}
|
|
|
|
// next returns the next ID from the generator. It is safe for concurrent use.
|
|
func (g *idGenerator) next() (id rulelist.URLFilterID) {
|
|
id32 := g.current.Add(1)
|
|
if id32 < 0 {
|
|
panic(fmt.Errorf("invalid current id value %d", id32))
|
|
}
|
|
|
|
return rulelist.URLFilterID(id32)
|
|
}
|
|
|
|
// fix ensures that flts all have unique IDs.
|
|
func (g *idGenerator) fix(flts []FilterYAML) {
|
|
set := container.NewMapSet[rulelist.URLFilterID]()
|
|
for i, f := range flts {
|
|
id := f.ID
|
|
if id == 0 {
|
|
id = g.next()
|
|
flts[i].ID = id
|
|
}
|
|
|
|
if !set.Has(id) {
|
|
set.Add(id)
|
|
|
|
continue
|
|
}
|
|
|
|
newID := g.next()
|
|
for set.Has(newID) {
|
|
newID = g.next()
|
|
}
|
|
|
|
log.Info(
|
|
"filtering: warning: filter at index %d has duplicate id %d; reassigning to %d",
|
|
i,
|
|
id,
|
|
newID,
|
|
)
|
|
|
|
flts[i].ID = newID
|
|
set.Add(newID)
|
|
}
|
|
}
|