reduce size

This commit is contained in:
Alon Zakai 2006-12-05 09:22:53 +00:00
parent 9522863ac3
commit 1d984b810f
4 changed files with 146 additions and 40 deletions

View File

@ -1,6 +1,6 @@
#
# Copyright (C) 2006 Zach Tibbitts <zach@collegegeek.org>
# Copyright (C) 2006 Alon Zakai ('Kripken') <kripkensteiner@gmail.com>
# Copyright (C) 2006 Zach Tibbitts <zach@collegegeek.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -17,11 +17,13 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# pytorrent-manager: backend/non-gui routines, that are not part of the core
# pytorrent module. pytorrent itself is mainly an interface to libtorrent,
# with some arrangements of exception classes for Python, etc.; also, some
# additional code that fits in well at the C++ level of libtorrent. All other
# backend routines should be in pytorrent-manager.
# Deluge Library, a.k.a. pytorrent:
#
# Deluge is a client. pytorrent is a Python library for torrenting, that includes
# pytorrent.py, which is Python code, and pytorrent_core, which is also a Python
# module, but written in C++, and includes the libtorrent torrent library. Only
# pytorrent should be visible, and only it should be imported, in the client.
#
import pytorrent_core
@ -33,13 +35,16 @@ import time
# Constants
TORRENTS_SUBDIR = "torrentfiles"
STATE_FILENAME = "persistent.state"
PREFS_FILENAME = "prefs.state"
DHT_FILENAME = "dht.state"
TORRENT_STATE_EXPIRATION = 1 # seconds, like the output of time.time()
DEFAULT_PREFS = {
# "max_half_open" : -1,
# "max_uploads" : -1 # Per torrent, read the libtorrent docs
"max_uploads" : 2, # a.k.a. upload slots
"listen_on" : [6881,9999],
"max_connections" : 80,
"use_DHT" : True,
@ -49,6 +54,14 @@ DEFAULT_PREFS = {
"max_upload_rate" : -1
}
# Exception
class PyTorrentError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
# Information for a single torrent
@ -99,6 +112,10 @@ class manager:
# Unique IDs are NOT in the state, since they are temporary for each session
self.unique_IDs = {} # unique_ID -> a torrent object
# Saved torrent states. We do not poll the core in a costly manner, necessarily
self.saved_torrent_states = {} # unique_ID -> torrent_state
self.saved_torrent_states_timestamp = {} # time of creation
# Unpickle the preferences, or create a new one
try:
pkl_file = open(self.base_dir + "/" + PREFS_FILENAME, 'rb')
@ -107,9 +124,10 @@ class manager:
except IOError:
self.prefs = DEFAULT_PREFS
# Apply preferences. Note that this is before any torrents are added
self.apply_prefs()
# Apply DHT, if needed
# Apply DHT, if needed. Note that this is before any torrents are added
if self.get_pref('use_DHT'):
pytorrent_core.start_DHT(self.base_dir + "/" + DHT_FILENAME)
@ -155,7 +173,14 @@ class manager:
self.prefs[key] = DEFAULT_PREFS[key]
return self.prefs[key]
else:
raise PyTorrentCoreError("Asked for a pref that doesn't exist: " + key)
raise PyTorrentError("Asked for a pref that doesn't exist: " + key)
def set_pref(self, key, value):
# Make sure this is a valid key
if key not in DEFAULT_PREFS.keys():
raise PyTorrentError("Asked to change a pref that isn't valid: " + key)
self.prefs[key] = value
def apply_prefs(self):
pytorrent_core.set_download_rate_limit(self.get_pref('max_download_rate')*1024)
@ -165,10 +190,11 @@ class manager:
pytorrent_core.set_listen_on(self.get_pref('listen_on')[0],
self.get_pref('listen_on')[1])
pytorrent_core.set_max_connections(self.get_pref('max_connections')*1024)
pytorrent_core.set_max_connections(self.get_pref('max_connections'))
pytorrent_core.set_max_uploads(self.get_pref('max_uploads'))
def add_torrent(self, filename, save_dir, compact):
print "add_torrent"
self.add_torrent_ns(filename, save_dir, compact)
return self.sync() # Syncing will create a new torrent in the core, and return it's ID
@ -204,8 +230,20 @@ class manager:
for unique_ID in self.unique_IDs:
pytorrent_core.save_fastresume(unique_ID, self.unique_IDs[unique_ID].filename)
def get_state(self, unique_ID):
return pytorrent_core.get_state(unique_ID)
# Efficient get_state: use a saved state, if it hasn't expired yet
def get_state(self, unique_ID, efficiently = False):
if efficiently:
try:
if time.time() < self.saved_torrent_states_timestamp[unique_ID] + \
TORRENT_STATE_EXPIRATION:
return self.saved_torrent_states[unique_ID]
except KeyError:
pass
self.saved_torrent_states_timestamp[unique_ID] = time.time()
self.saved_torrent_states[unique_ID] = pytorrent_core.get_state(unique_ID)
return self.saved_torrent_states[unique_ID]
def queue_up(self, unique_ID):
curr_index = self.get_queue_index(unique_ID)
@ -229,7 +267,7 @@ class manager:
def clear_completed(self):
for unique_ID in self.unique_IDs:
torrent_state = pytorrent_core.get_state(unique_ID)
torrent_state = self.get_state(unique_ID, True)
if torrent_state['progress'] == 100.0:
self.remove_torrent_ns(unique_ID)
@ -242,9 +280,6 @@ class manager:
def is_user_paused(self, unique_ID):
return self.unique_IDs[unique_ID].user_paused
def is_paused(self, unique_ID):
return pytorrent_core.is_paused(unique_ID)
# Enforce the queue: pause/unpause as needed, based on queue and user_pausing
# This should be called after changes to relevant parameters (user_pausing, or
# altering max_active_torrents), or just from time to time
@ -255,7 +290,7 @@ class manager:
if self.auto_seed_ratio != -1:
for unique_ID in self.unique_IDs:
if pytorrent_core.is_seeding(unique_ID):
torrent_state = pytorrent_core.get_state(unique_ID)
torrent_state = self.get_state(unique_ID, True)
ratio = self.calc_ratio(unique_ID, torrent_state)
if ratio >= self.auto_seed_ratio:
self.queue_bottom(unique_ID)
@ -264,10 +299,10 @@ class manager:
for index in range(len(self.state.queue)):
unique_ID = self.state.queue[index]
if (index < self.state.max_active_torrents or self.state_max_active_torrents == -1) \
and self.is_paused(unique_ID) \
and pytorrent_core.is_paused(unique_ID) \
and not self.is_user_paused(unique_ID):
pytorrent_core.resume(unique_ID)
elif not self.is_paused(unique_ID) and \
elif not pytorrent_core.is_paused(unique_ID) and \
(index >= self.state.max_active_torrents or self.is_user_paused(unique_ID)):
pytorrent_core.pause(unique_ID)
@ -282,6 +317,8 @@ class manager:
return ret
def get_num_torrents(self):
return pytorrent_core.get_num_torrents()
####################
# Internal functions
@ -298,7 +335,7 @@ class manager:
full_new_name = self.base_dir + "/" + TORRENTS_SUBDIR + "/" + new_name
if new_name in os.listdir(self.base_dir + "/" + TORRENTS_SUBDIR):
raise PyTorrentCoreError("Could not cache torrent file locally, failed: " + new_name)
raise PyTorrentError("Could not cache torrent file locally, failed: " + new_name)
shutil.copy(filename, full_new_name)
@ -314,8 +351,6 @@ class manager:
# Also all self-syncing is done here (various lists)
def sync(self):
print "sync"
ret = None # We return new added unique ID(s), or None
# Add torrents to core and unique_IDs
@ -323,11 +358,11 @@ class manager:
for torrent in self.state.torrents:
if torrent not in torrents_with_unique_ID:
print "Adding torrent to core:", torrent.filename, torrent.save_dir, torrent.compact
# print "Adding torrent to core:", torrent.filename, torrent.save_dir, torrent.compact
unique_ID = pytorrent_core.add_torrent(torrent.filename,
torrent.save_dir,
torrent.compact)
print "Got unique ID:", unique_ID
# print "Got unique ID:", unique_ID
ret = unique_ID
self.unique_IDs[unique_ID] = torrent

65
library/run_setup.py Normal file
View File

@ -0,0 +1,65 @@
#
# Copyright (c) 2006 Alon Zakai ('Kripken') <kripkensteiner@gmail.com>
#
# 2006-15-9
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
import sys
command = sys.argv[1]
assert(command in ['build', 'install'])
removals = ['-g', '-DNDEBUG', '-O2', '-Wstrict-prototypes']
addition = "-DNDEBUG -Os"
import platform
pythonVersion = platform.python_version()[0:3]
print "========================================="
print "Creating pytorrent_core for Python " + pythonVersion
print "========================================="
import os
p = os.popen("python setup.py --dry-run build")
data = p.readlines()
p.close()
print "Executing modified commands: "
for line in data:
if line[0:3] in ['gcc', 'g++']:
# print "OLD: ", line
for removal in removals:
line = line.replace(" " + removal + " ", " ")
line = line[0:4] + addition + " " + line[4:]
print line
p = os.popen(line)
data = p.readlines()
p.close()
print ""
# Now redo it, for real. Nothing should occur, except for installation, if requested
print "Finalizing..."
p = os.popen("python setup.py " + command)
data = p.readlines()
p.close()
print "".join(data)

View File

@ -22,10 +22,6 @@ import platform
pythonVersion = platform.python_version()[0:3]
print "========================================="
print "Creating pytorrent_core for Python " + pythonVersion
print "========================================="
from distutils.core import setup, Extension
module1 = Extension('pytorrent_core',
@ -34,6 +30,8 @@ module1 = Extension('pytorrent_core',
libraries = ['boost_filesystem', 'boost_date_time',
'boost_program_options', 'boost_regex',
'boost_serialization', 'boost_thread', 'z', 'pthread'],
extra_compile_args = ["-Wno-missing-braces"],
# extra_link_args = [""],
sources = ['alert.cpp',
'allocate_resources.cpp',
'bt_peer_connection.cpp',
@ -68,7 +66,10 @@ module1 = Extension('pytorrent_core',
'./kademlia/rpc_manager.cpp',
'./kademlia/traversal_algorithm.cpp'])
setup (name = 'pytorrent_core',
version = '0.5.0',
description = 'Wrapper code for libtorrent C++ torrent library (Sourceforge, not Rakshasa)',
ext_modules = [module1])
setup(name = 'pytorrent_core',
version = '0.5.0',
description = 'A module for the bittorrent protocol. Built using (Sourgeforge, not Rakshasha) libtorrent.',
author="Alon Zakai ('Kripken'), Zach Tibbitts",
author_email="kripkensteiner@gmail.com",
url="http://www.deluge-torrent.org",
ext_modules = [module1])

View File

@ -16,15 +16,20 @@ import os
manager = pytorrent.manager("PT", "0500", "pytorrent - testing only",
os.path.expanduser("~") + "/Temp")
#manager.prefs['max_active_torrents'] = 1
#my_torrent = manager.add_torrent("ubuntu.torrent", ".", True)
#print "Unique ID:", my_torrent
for i in range(2):
print "STATE:"
print manager.get_state(0)#my_torrent)
print ""
print "PREFS:", manager.prefs
sleep(2)
manager.quit()
try:
while True:
print "STATE:", manager.get_num_torrents()
for j in range(manager.get_num_torrents()):
print manager.get_state(j)
print ""
sleep(2)
except KeyboardInterrupt:
manager.quit()