This forum has been archived. All content is frozen. Please use KDE Discuss instead.

[feature request] Randomize seeds / Poorly Seeded torrents

Tags: None
(comma "," separated)
wildcard
Registered Member
Posts
5
Karma
0
Can you add some sort of option for randomizing seeds?

I would like something that would go through my list of torrents and randomly select some to seed with a configurable time when it will re-randomize. It will keep adding seeds until my bandwidth is fully utilized. If a seed drops off bandwidth, it would pick another torrent to seed.

Also, can you add some sort of option for prioritizing seeds? I would like the poorly seeded torrents to have priority over heavily seeded torrents.
ShadowTek
Registered Member
Posts
7
Karma
0

Sun Aug 16, 2009 3:53 am
I have yet to find a torrent client that provides a configurable seeding-priority scheme that satisfies my needs.

I think the best way to build one would be to give the user a set of configuration options including *if/then/else* structures and *and/or* comparisons.

If the ktorrent queue manager could be configured to this level of depth, it would put Vuze to shame.

But please don't integrate such an idea into the scripting plugin, as it doesn't seem to work on Gnome.
George
Moderator
Posts
5421
Karma
1

Re:

Sun Aug 16, 2009 9:43 am
But please don't integrate such an idea into the scripting plugin, as it doesn't seem to work on Gnome.


It should work on any desktop environment
Rioting_Pacifist
Registered Member
Posts
27
Karma
0
ShadowTek wrote:But please don't integrate such an idea into the scripting plugin, as it doesn't seem to work on Gnome.
I found the main problem with kross is that many distros don't actually ship it and of those that do some don't ship the kross-python binding (or kross-anything)

The reason i say this is that I have been thinking about implementing this as a script, but i've been distracted by other stuff (e.g my grouping script).
*if/then/else* structures and *and/or*
, it seams like this is defiantly suited to a calling a simple script, however to start with i was thinking of something easy like DO NOT RUN AS SLEEPING CAUSES KTORRENT TO SLEEP
Code: Select all
#!/usr/biclan/env kross
# -*- coding: utf-8 -*-
import KTorrent
import Kross
import time
import random
import KTScriptingPlugin

def run():
   maxSeeds=30
   waitTime=1800 #time to wait while at fullspeed
   targetSpeed = 5
   startTime=90 #time to wait for a torrent to hit fullspeed
   lst = getList(maxSeeds)
   while True:
      running = startSeeds(lst,startTime)
      time.sleep(waitTime)
      lst = getList(maxSeeds)
      stopSeeds(running)

def getList(maxSeeds):
   lst = []
   for ih in KTorrent.torrents():
      tor = KTorrent.torrent(ih)
      seeds = tor.seedersTotal()
      if seeds == 0:
         tor.scrape()
         time.sleep(30)      #this
         seeds = tor.seedersTotal()
         KTorrent.log(str(seeds))
      leechs = tor.leechersTotal()
      if seeds < maxSeeds and leechs > 0 :
         lst.append(ih)
   return lst

def stopSeeds(lst):
   for ih in running:
      KTorrent.stop(ih)

def startSeeds(lst,targetSpeed,startTime):
   running = []
   while speed < targetspeed:
      choice = random.randint(0,len(lst))-1
      ih = lst.pop(choice)
      running.append(ih)
      KTorrent.start(ih)
      time.sleep(startTime)
   return running

run()

I have to go do stuff, but this code is hopefully a start, the sleep function needs to be replaced with either threading OR KTScriptingPlugin.createTimer(True)
hope this helps somebody finish this off
p.s please post if there is an easy way to implement a sleep equivalent for just one one script, otherwise the script will need to be totally redesigned ( first call scrape for all needed torrents> "sleep for a ?60s?> stop/start torrents > "sleep for timeout" > back to start), it probably isn't too hard, but thought ill leave this code here incase its useful

Last edited by Rioting_Pacifist on Fri Aug 21, 2009 3:16 pm, edited 1 time in total.
George
Moderator
Posts
5421
Karma
1
I haven't tried threading in kross scripts, should work but the big problem is when you start calling ktorrent functions, most of them are not thread safe.

The easiest way to sleep is using createTimer, it integrates well with the Qt event loop, and doesn't result in all the dangers associated with threading.
ShadowTek
Registered Member
Posts
7
Karma
0
RiotingPacifist wrote: I found the main problem with kross is that many distros don't actually ship it and of those that do some don't ship the kross-python binding (or kross-anything)

http://kross.dipe.org/solution.html wrote:The Kross code and the JavaScript plugin are included in kdelibs.


Well I've installed every kdelibs* package in the Ubuntu repository, and I still can't even get this to work:
Code: Select all
#!/usr/bin/env kross
import KTorrent
import KTScriptingPlugin
import Kross

KTorrent.log("Hello World !")

http://ktorrent.org/wiki/index.php/Writing_Scripts

Edit: By the way, I'm using the Ubuntu package for ktorrent 3.2.1, along with all other KDE dependencies coming from Ubuntu packages.
Rioting_Pacifist
Registered Member
Posts
27
Karma
0
Code: Select all
The Kross code and the JavaScript plugin are included in kdelibs.

AFAIK kdelibs only refers to the kde version of the code, distros then cut it up and repackage it so there is no guarantee the just because you have all of "kdelibs" installed that you have the js plugin (if i was packaging kde id put it under kross-js), what does
Code: Select all
apt-cache search kross

return.

My scripts should work, there are 2 versions 0.2 has a static delay after scraping trackers 0.3 is less tested but waits 5s for the reply to each scrape. They don't do exactly what you asked for as you need to define the targetUpload, tbh if you just want to saturate your bandwidth do you want to just leave them all running and rotate the priorities (if that's what you want i can probably change the script to do that (hell its probably a lot easier than this).
The scripts are just the plain python scripts (listed below due to forum choice) so will need to be installed manually, they will also need to configured by hand.
BUGS:
Only works if torrents are running (see below)
Will add all torrents if your target is higher than your upload cap
Does not free-up ram on exit
Exit code causes raises an error (tbh im not sure how to exit the loop correctly)

TODO:
Move all torrents into a group (expect that today/tomorow)
Add gui configuration (will take me a while, but i'll accept somebody elses help on this :wink: )
Figure out how a better way to get the targetUpload than a static definition

The bug
I think my script should work, unfortunately started torrents don't seam to start (but do up in the the the tab numbers) unless you already have a torrent running, the relevant code is
Code: Select all
   def startASeed(self):
      choice = random.randint(0,(len(self.candidates)-1))
      ih = self.candidates.pop(choice)
      KTorrent.start(ih)
      self.running.append(ih)
      KTorrent.log(KTorrent.torrent(ih).name()+" added to seeds, sleeping for"+str(self.seedAddedWait)+"ms")
      self.timer.start(self.seedAddedWait)


p.s can somebody recommend good defaults the delays i'm not tormenting much atm (brother is using xbox live all day) so haven't had time to tweak them
self.seedAddedWait (currently 30s)
self.trackerWait (currently 60s or 5s per torrent)

It turns out the forum doesn't like attachments here are the scripts:
Code: Select all
#!/usr/biclan/env kross
# -*- coding: utf-8 -*-
import KTorrent
import Kross
import random
import KTScriptingPlugin
class reviver:
   def __init__(self):
      #settings for you
      self.randomiseWait = 1800000 #time in ms
      self.targetSpeed = 20
      self.maxSeeds = 40
      
      #settings to tweak script
      self.scriptName = "reviver 0.2: "
      self.trackerWait = 60000
      self.seedAddedWait = 30000
      
      #internals
      self.run = True
      self.state = 0
      self.candidates = []
      self.running = []
      
      self.timer = KTScriptingPlugin.createTimer(True)
      self.timer.connect('timeout()',self.timerFired)

   def timerFired(self):
      if self.run == True:
         if self.state == 0:
            self.scrapeTrackers()
         elif self.state == 1:
            self.setCandidates()
            self.stopSeeds()
            self.state = 2
         if self.state == 2:
            if (self.speed() < self.targetSpeed) and (len(self.candidates) > 0):
               self.startASeed()
            else:
               self.state = 0
               self.timer.start(self.randomiseWait)
               if len(self.candidates) > 0: KTorrent.log(self.scriptName+"reached target, sleeping for "+str(self.randomiseWait)+"ms")
               else: KTorrent.log(self.scriptName+"no candidates left, sleeping for "+str(self.randomiseWait)+"ms")


   def scrapeTrackers(self):
      for ih in KTorrent.torrents():
         tor = KTorrent.torrent(ih)
         if tor.seedersTotal() == 0:
            KTorrent.log(self.scriptName+"scraping "+tor.name())
            tor.scrape()
      KTorrent.log(self.scriptName+"trackers scraped sleeping for "+str(self.trackerWait)+"ms")
      self.state = 1
      self.timer.start(self.trackerWait)

   def setCandidates(self):
      self.candidates = []
      for ih in KTorrent.torrents():
         tor = KTorrent.torrent(ih)
         if ih in self.running or tor.downloadSpeed() + tor.uploadSpeed() == 0:      #dont mess with user torrents that makes them angry
            if (tor.leechersTotal() > 0) and (tor.seedersTotal() <= self.maxSeeds):
               self.candidates.append(ih)
      KTorrent.log(self.scriptName+str(len(self.candidates))+" candidates found")

   def startASeed(self):
      choice = random.randint(0,(len(self.candidates)-1))
      ih = self.candidates.pop(choice)
      KTorrent.start(ih)
      self.running.append(ih)
      KTorrent.log(KTorrent.torrent(ih).name()+" added to seeds, sleeping for"+str(self.seedAddedWait)+"ms")
      self.timer.start(self.seedAddedWait)

   def stopSeeds(self):
      for ih in self.running:
         KTorrent.stop(ih)
      self.running = []
      KTorrent.log(self.scriptName+"seeds stoped")

   def speed(self):
      speed = 0
      for ih in self.running:
         tor = KTorrent.torrent(ih)
         speed += tor.uploadSpeed()
      return speed

reviverscripts = reviver()
reviverscripts.scrapeTrackers()

def unload():
   reviverscripts.run = False
        reviverscripts.stopSeeds()


Code: Select all
class reviver:
   def __init__(self):
      #settings for you
      self.randomiseWait = 1800000 #time in ms
      self.targetSpeed = 20
      self.maxSeeds = 40
      
      #settings to tweak script
      self.scriptName = "reviver 0.3: "
      self.trackerWait = 1000
      self.seedAddedWait = 30000
      
      #internals
      self.run = True
      self.state = 0
      self.toScrape = []
      self.candidates = []
      self.running = []
      
      self.timer = KTScriptingPlugin.createTimer(True)
      self.timer.connect('timeout()',self.timerFired)

   def timerFired(self):
      if self.run == True:
         if self.state == 0:
            self.getScrapeTargets()
         if self.state == 1:
            if len(self.toScrape) > 0:
               self.scrapeATracker()
            else:
               self.setCandidates()
               self.stopSeeds()
               self.state = 2
         if self.state == 2:
            if self.speed() < self.targetSpeed and len(self.candidates) > 0:
               self.startASeed()
            else:
               if len(self.candidates) > 0: KTorrent.log(self.scriptName+"reached target, sleeping for "+str(self.randomiseWait)+"ms")
               else: KTorrent.log(self.scriptName+"no candidates left, sleeping for "+str(self.randomiseWait)+"ms")
               self.state = 0
               self.timer.start(self.randomiseWait)

   def getScrapeTargets(self):
      for ih in KTorrent.torrents():
         tor = KTorrent.torrent(ih)
         if tor.seedersTotal() == 0:
            self.toScrape.append(ih)
      KTorrent.log(self.scriptName+"got scrape targets "+str(len(self.toScrape)))
      self.state = 1

   def scrapeATracker(self):
      target = self.toScrape.pop(0)
      tor = KTorrent.torrent(target)
      tor.scrape()
      KTorrent.log(self.scriptName+"scraping "+tor.name()+" waiting "+str(self.trackerWait)+"ms for reply")
      self.timer.start(self.trackerWait)

   def setCandidates(self):
      self.candidates = []
      for ih in KTorrent.torrents():
         tor = KTorrent.torrent(ih)
         if ih in self.running or tor.downloadSpeed() + tor.uploadSpeed() == 0:      #dont mess with user torrents that makes them angry
            if (tor.leechersTotal() > 0) and (tor.seedersTotal() <= self.maxSeeds):
               self.candidates.append(ih)
      KTorrent.log(self.scriptName+str(len(self.candidates))+" candidates found")

   def startASeed(self):
      choice = random.randint(0,(len(self.candidates)-1))
      ih = self.candidates.pop(choice)
      KTorrent.start(ih)
      self.running.append(ih)
      KTorrent.log(KTorrent.torrent(ih).name()+" added to seeds, sleeping for"+str(self.seedAddedWait)+"ms")
      self.timer.start(self.seedAddedWait)

   def stopSeeds(self):
      for ih in self.running:
         KTorrent.stop(ih)
      self.running = []
      KTorrent.log(self.scriptName+"seeds stoped")

   def speed(self):
      speed = 0
      for ih in self.running:
         tor = KTorrent.torrent(ih)
         speed += tor.uploadSpeed()
      return speed

reviverscripts = reviver()
reviverscripts.timerFired()

def unload():
   reviverscripts.run = False
   reviverscripts.stopSeeds()


edit: spelt reviver correctly
And additional snippet to add the groups to the groups menu when bug203922 is fixed, replaces lines 97 onwards
Code: Select all
class funcGroup:
   def __init__(self,func):
      self.func = func
   
   def isMember(self,tor):
      return self.func(tor)

class reviverFuncs:
   def __init__(self):
      pass
   
   def isViable(self,tor):
      return tor.seedersTotal() <= reviverscripts.maxSeeds
      
   def isUnwanted(self,tor):
      return self.isViable(tor) and tor.leechersTotal() == 0
   
   def isActive(self,tor):
      return tor.infoHash() in reviverscripts.running
   
   def isInactive(self,tor):
      return tor.infoHash() in reviverscripts.candidates
      

def mkGroups():
   f=reviverFuncs()
   KTScriptingPlugin.addGroup("Reviver","daemon","/all/Reviver",funcGroup(f.isViable))
   KTScriptingPlugin.addGroup("Active","player_play","/all/Reviver/Active",funcGroup(f.isActive))
   KTScriptingPlugin.addGroup("Inactive","player_pause","/all/Reviver/Inactive",funcGroup(f.isInactive))
   KTScriptingPlugin.addGroup("Unwanted","player_stop","/all/Reviver/Unwanted",funcGroup(f.isUnwanted))

reviverscripts = reviver()
mkGroups()
reviverscripts.timerFired()

def unload():
   reviverscripts.run = False
   for s in "Reviver","Active","Inactive","Unwanted":
      KTScriptingPlugin.removeGroup(s)
   reviverscripts.stopSeeds()

Last edited by Rioting_Pacifist on Sat Aug 22, 2009 5:39 pm, edited 2 times in total.
ShadowTek
Registered Member
Posts
7
Karma
0
RiotingPacifist wrote:what does
Code: Select all
apt-cache search kross

return.


I already have the ruby and python plugins, which are all that I see.
Code: Select all
user@user-desktop:~$ apt-cache search kross
ktorrent - BitTorrent client based on the KDE 4 technology platform
libkrosspython0 - Kross scripting framework for KDE 4 - Python component
ggz-game-servers - GGZ Gaming Zone: game servers collection
ggz-kde-games - GGZ Gaming Zone: game clients collection for KDE
libkrossruby0 - Kross scripting framework for KDE 4 - Ruby component
Rioting_Pacifist
Registered Member
Posts
27
Karma
0
I don't know much about kross, other than it was designed to do stuff like this, instead of having a million features, having a million optional scripts, but there is no reason it shouldn't work in gnome, i suspect it is a bug in either the version of ktorrent/kde you have or you packaging (do your logs give any hints as to why errors? btw this should probably be in a different thread, and your likely to get better help on a ubuntuorums (or maybe kde forums), as there is no reason gnome/kde apps can't work together fully, other than packaging.


Bookmarks



Who is online

Registered users: Bing [Bot], Evergrowing, Google [Bot]