Skip to content

Commit

Permalink
'MapHardlinksFor' filter config option
Browse files Browse the repository at this point in the history
  • Loading branch information
SweetMnM committed Nov 16, 2022
1 parent d57e91e commit 2cecd67
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 71 deletions.
40 changes: 24 additions & 16 deletions cmd/clean.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/l3uddz/tqm/expression"
"github.com/l3uddz/tqm/hardlinkfilemap"
"github.com/l3uddz/tqm/logger"
"github.com/l3uddz/tqm/sliceutils"
"github.com/l3uddz/tqm/torrentfilemap"
"github.com/l3uddz/tqm/tracker"
)
Expand Down Expand Up @@ -118,24 +119,31 @@ var cleanCmd = &cobra.Command{
tfm := torrentfilemap.New(torrents)
log.Infof("Mapped torrents to %d unique torrent files", tfm.Length())

// download path mapping
clientDownloadPathMapping, err := getClientDownloadPathMapping(clientConfig)
if err != nil {
log.WithError(err).Fatal("Failed loading client download path mappings")
} else if clientDownloadPathMapping != nil {
log.Debugf("Loaded %d client download path mappings: %#v", len(clientDownloadPathMapping),
clientDownloadPathMapping)
}
var hfm hardlinkfilemap.HardlinkFileMapI
if sliceutils.StringSliceContains(clientFilter.MapHardlinksFor, "clean", true) {
// download path mapping
clientDownloadPathMapping, err := getClientDownloadPathMapping(clientConfig)
if err != nil {
log.WithError(err).Fatal("Failed loading client download path mappings")
} else if clientDownloadPathMapping != nil {
log.Debugf("Loaded %d client download path mappings: %#v", len(clientDownloadPathMapping),
clientDownloadPathMapping)
}

// create map of paths associated to underlying file ids
start := time.Now()
hfm := hardlinkfilemap.New(torrents, clientDownloadPathMapping)
log.Infof("Mapped all torrent file paths to %d unique underlying file IDs in %s", hfm.Length(), time.Since(start))
// create map of paths associated to underlying file ids
start := time.Now()
hfm = hardlinkfilemap.New(torrents, clientDownloadPathMapping)
log.Infof("Mapped all torrent file paths to %d unique underlying file IDs in %s", hfm.Length(), time.Since(start))

// add HardlinkedOutsideClient field to torrents
for h, t := range torrents {
t.HardlinkedOutsideClient = hfm.HardlinkedOutsideClient(t)
torrents[h] = t
// add HardlinkedOutsideClient field to torrents
for h, t := range torrents {
t.HardlinkedOutsideClient = hfm.HardlinkedOutsideClient(t)
torrents[h] = t
}
} else {
log.Warnf("Not mapping hardlinks for client %q", clientName)
log.Warnf("If your setup involves multiple torrents sharing the same underlying file using hardlinks, or you are using the 'HardlinkedOutsideClient' field in your filters, you should add 'clean' to the 'MapHardlinksFor' field in your filter configuration")
hfm = hardlinkfilemap.NewNoopHardlinkFileMap()
}

// remove torrents that are not ignored and match remove criteria
Expand Down
5 changes: 2 additions & 3 deletions cmd/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ func removeSlice(slice []string, remove []string) []string {
}

// retag torrent that meet required filters
func retagEligibleTorrents(log *logrus.Entry, c client.TagInterface, torrents map[string]config.Torrent,
tfm *torrentfilemap.TorrentFileMap) error {
func retagEligibleTorrents(log *logrus.Entry, c client.TagInterface, torrents map[string]config.Torrent) error {
// vars
ignoredTorrents := 0
retaggedTorrents := 0
Expand Down Expand Up @@ -154,7 +153,7 @@ func relabelEligibleTorrents(log *logrus.Entry, c client.Interface, torrents map

// remove torrents that meet remove filters
func removeEligibleTorrents(log *logrus.Entry, c client.Interface, torrents map[string]config.Torrent,
tfm *torrentfilemap.TorrentFileMap, hfm *hardlinkfilemap.HardlinkFileMap) error {
tfm *torrentfilemap.TorrentFileMap, hfm hardlinkfilemap.HardlinkFileMapI) error {
// vars
ignoredTorrents := 0
hardRemoveTorrents := 0
Expand Down
36 changes: 21 additions & 15 deletions cmd/relabel.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/l3uddz/tqm/expression"
"github.com/l3uddz/tqm/hardlinkfilemap"
"github.com/l3uddz/tqm/logger"
"github.com/l3uddz/tqm/sliceutils"
"github.com/l3uddz/tqm/torrentfilemap"
"github.com/l3uddz/tqm/tracker"
)
Expand Down Expand Up @@ -118,23 +119,28 @@ var relabelCmd = &cobra.Command{
tfm := torrentfilemap.New(torrents)
log.Infof("Mapped torrents to %d unique torrent files", tfm.Length())

// download path mapping
clientDownloadPathMapping, err := getClientDownloadPathMapping(clientConfig)
if err != nil {
log.WithError(err).Fatal("Failed loading client download path mappings")
} else if clientDownloadPathMapping != nil {
log.Debugf("Loaded %d client download path mappings: %#v", len(clientDownloadPathMapping),
clientDownloadPathMapping)
}
if sliceutils.StringSliceContains(clientFilter.MapHardlinksFor, "relabel", true) {
// download path mapping
clientDownloadPathMapping, err := getClientDownloadPathMapping(clientConfig)
if err != nil {
log.WithError(err).Fatal("Failed loading client download path mappings")
} else if clientDownloadPathMapping != nil {
log.Debugf("Loaded %d client download path mappings: %#v", len(clientDownloadPathMapping),
clientDownloadPathMapping)
}

// create map of paths associated to underlying file ids
start := time.Now()
hfm := hardlinkfilemap.New(torrents, clientDownloadPathMapping)
log.Infof("Mapped all torrent file paths to %d unique underlying file IDs in %s", hfm.Length(), time.Since(start))
// create map of paths associated to underlying file ids
start := time.Now()
hfm := hardlinkfilemap.New(torrents, clientDownloadPathMapping)
log.Infof("Mapped all torrent file paths to %d unique underlying file IDs in %s", hfm.Length(), time.Since(start))

// add HardlinkedOutsideClient field to torrents
for _, t := range torrents {
t.HardlinkedOutsideClient = hfm.HardlinkedOutsideClient(t)
// add HardlinkedOutsideClient field to torrents
for _, t := range torrents {
t.HardlinkedOutsideClient = hfm.HardlinkedOutsideClient(t)
}
} else {
log.Warnf("Not mapping hardlinks for client %q", clientName)
log.Warnf("If your setup involves multiple torrents sharing the same underlying file using hardlinks, or you are using the 'HardlinkedOutsideClient' field in your filters, you should add 'relabel' to the 'MapHardlinksFor' field in your filter configuration")
}

// relabel torrents that meet the filter criteria
Expand Down
43 changes: 22 additions & 21 deletions cmd/retag.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"github.com/l3uddz/tqm/expression"
"github.com/l3uddz/tqm/hardlinkfilemap"
"github.com/l3uddz/tqm/logger"
"github.com/l3uddz/tqm/torrentfilemap"
"github.com/l3uddz/tqm/sliceutils"
"github.com/l3uddz/tqm/tracker"
)

Expand Down Expand Up @@ -124,27 +124,28 @@ var retagCmd = &cobra.Command{
}
}

// create map of files associated to torrents (via hash)
tfm := torrentfilemap.New(torrents)
log.Infof("Mapped torrents to %d unique torrent files", tfm.Length())

// download path mapping
clientDownloadPathMapping, err := getClientDownloadPathMapping(clientConfig)
if err != nil {
log.WithError(err).Fatal("Failed loading client download path mappings")
} else if clientDownloadPathMapping != nil {
log.Debugf("Loaded %d client download path mappings: %#v", len(clientDownloadPathMapping),
clientDownloadPathMapping)
}
if sliceutils.StringSliceContains(clientFilter.MapHardlinksFor, "retag", true) {
// download path mapping
clientDownloadPathMapping, err := getClientDownloadPathMapping(clientConfig)
if err != nil {
log.WithError(err).Fatal("Failed loading client download path mappings")
} else if clientDownloadPathMapping != nil {
log.Debugf("Loaded %d client download path mappings: %#v", len(clientDownloadPathMapping),
clientDownloadPathMapping)
}

// create map of paths associated to underlying file ids
start := time.Now()
hfm := hardlinkfilemap.New(torrents, clientDownloadPathMapping)
log.Infof("Mapped all torrent file paths to %d unique underlying file IDs in %s", hfm.Length(), time.Since(start))
// create map of paths associated to underlying file ids
start := time.Now()
hfm := hardlinkfilemap.New(torrents, clientDownloadPathMapping)
log.Infof("Mapped all torrent file paths to %d unique underlying file IDs in %s", hfm.Length(), time.Since(start))

// add HardlinkedOutsideClient field to torrents
for _, t := range torrents {
t.HardlinkedOutsideClient = hfm.HardlinkedOutsideClient(t)
// add HardlinkedOutsideClient field to torrents
for _, t := range torrents {
t.HardlinkedOutsideClient = hfm.HardlinkedOutsideClient(t)
}
} else {
log.Warnf("Not mapping hardlinks for client %q", clientName)
log.Warnf("If your setup involves multiple torrents sharing the same underlying file using hardlinks, or you are using the 'HardlinkedOutsideClient' field in your filters, you should add 'retag' to the 'MapHardlinksFor' field in your filter configuration")
}

// Verify tags exist on client
Expand All @@ -159,7 +160,7 @@ var retagCmd = &cobra.Command{
}

// relabel torrents that meet the filter criteria
if err := retagEligibleTorrents(log, ct, torrents, tfm); err != nil {
if err := retagEligibleTorrents(log, ct, torrents); err != nil {
log.WithError(err).Fatal("Failed retagging eligible torrents...")
}
},
Expand Down
7 changes: 4 additions & 3 deletions config/filter.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package config

type FilterConfiguration struct {
Ignore []string
Remove []string
Label []struct {
MapHardlinksFor []string
Ignore []string
Remove []string
Label []struct {
Name string
Update []string
}
Expand Down
26 changes: 13 additions & 13 deletions hardlinkfilemap/hardlinkfilemap.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"github.com/scylladb/go-set/strset"
)

func New(torrents map[string]config.Torrent, torrentPathMapping map[string]string) *HardlinkFileMap {
func New(torrents map[string]config.Torrent, torrentPathMapping map[string]string) HardlinkFileMapI {
tfm := &HardlinkFileMap{
hardlinkFileMap: make(map[string]*strset.Set),
log: logger.GetLogger("hardlinkfilemap"),
Expand All @@ -23,7 +23,7 @@ func New(torrents map[string]config.Torrent, torrentPathMapping map[string]strin
return tfm
}

func (t *HardlinkFileMap) ConsiderPathMapping(path string) string {
func (t *HardlinkFileMap) considerPathMapping(path string) string {
for mapFrom, mapTo := range t.torrentPathMapping {
if strings.HasPrefix(path, mapFrom) {
return strings.Replace(path, mapFrom, mapTo, 1)
Expand All @@ -33,7 +33,7 @@ func (t *HardlinkFileMap) ConsiderPathMapping(path string) string {
return path
}

func (t *HardlinkFileMap) LinkInfoByPath(path string) (string, uint64, bool) {
func (t *HardlinkFileMap) linkInfoByPath(path string) (string, uint64, bool) {
stat, err1 := os.Stat(path)
if err1 != nil {
t.log.Warnf("Failed to stat file: %s - %s", path, err1)
Expand All @@ -51,9 +51,9 @@ func (t *HardlinkFileMap) LinkInfoByPath(path string) (string, uint64, bool) {

func (t *HardlinkFileMap) AddByTorrent(torrent config.Torrent) {
for _, f := range torrent.Files {
f = t.ConsiderPathMapping(f)
f = t.considerPathMapping(f)

id, _, ok := t.LinkInfoByPath(f)
id, _, ok := t.linkInfoByPath(f)

if !ok {
continue
Expand All @@ -72,9 +72,9 @@ func (t *HardlinkFileMap) AddByTorrent(torrent config.Torrent) {

func (t *HardlinkFileMap) RemoveByTorrent(torrent config.Torrent) {
for _, f := range torrent.Files {
f = t.ConsiderPathMapping(f)
f = t.considerPathMapping(f)

id, _, ok := t.LinkInfoByPath(f)
id, _, ok := t.linkInfoByPath(f)

if !ok {
continue
Expand All @@ -94,9 +94,9 @@ func (t *HardlinkFileMap) RemoveByTorrent(torrent config.Torrent) {
}
}

func (t *HardlinkFileMap) CountLinks(f string) (inmap uint64, total uint64, ok bool) {
f = t.ConsiderPathMapping(f)
id, nlink, ok := t.LinkInfoByPath(f)
func (t *HardlinkFileMap) countLinks(f string) (inmap uint64, total uint64, ok bool) {
f = t.considerPathMapping(f)
id, nlink, ok := t.linkInfoByPath(f)

if !ok {
return 0, 0, false
Expand All @@ -111,7 +111,7 @@ func (t *HardlinkFileMap) CountLinks(f string) (inmap uint64, total uint64, ok b

func (t *HardlinkFileMap) HardlinkedOutsideClient(torrent config.Torrent) bool {
for _, f := range torrent.Files {
inmap, total, ok := t.CountLinks(f)
inmap, total, ok := t.countLinks(f)
if !ok {
continue
}
Expand All @@ -126,7 +126,7 @@ func (t *HardlinkFileMap) HardlinkedOutsideClient(torrent config.Torrent) bool {

func (t *HardlinkFileMap) IsTorrentUnique(torrent config.Torrent) bool {
for _, f := range torrent.Files {
c, _, ok := t.CountLinks(f)
c, _, ok := t.countLinks(f)
if !ok {
return false
}
Expand All @@ -141,7 +141,7 @@ func (t *HardlinkFileMap) IsTorrentUnique(torrent config.Torrent) bool {

func (t *HardlinkFileMap) NoInstances(torrent config.Torrent) bool {
for _, f := range torrent.Files {
c, _, ok := t.CountLinks(f)
c, _, ok := t.countLinks(f)
if !ok {
return false
}
Expand Down
12 changes: 12 additions & 0 deletions hardlinkfilemap/interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package hardlinkfilemap

import "github.com/l3uddz/tqm/config"

type HardlinkFileMapI interface {
AddByTorrent(torrent config.Torrent)
RemoveByTorrent(torrent config.Torrent)
NoInstances(torrent config.Torrent) bool
IsTorrentUnique(torrent config.Torrent) bool
HardlinkedOutsideClient(torrent config.Torrent) bool
Length() int
}
32 changes: 32 additions & 0 deletions hardlinkfilemap/noophardllinkfilemap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package hardlinkfilemap

import "github.com/l3uddz/tqm/config"

type noopHardlinkFileMap struct {
}

func NewNoopHardlinkFileMap() *noopHardlinkFileMap {
return &noopHardlinkFileMap{}
}

func (h *noopHardlinkFileMap) AddByTorrent(torrent config.Torrent) {
}

func (h *noopHardlinkFileMap) RemoveByTorrent(torrent config.Torrent) {
}

func (h *noopHardlinkFileMap) NoInstances(torrent config.Torrent) bool {
return true
}

func (h *noopHardlinkFileMap) IsTorrentUnique(torrent config.Torrent) bool {
return true
}

func (h *noopHardlinkFileMap) HardlinkedOutsideClient(torrent config.Torrent) bool {
return false
}

func (h *noopHardlinkFileMap) Length() int {
return 0
}

0 comments on commit 2cecd67

Please sign in to comment.