I think I've managed to fix this using the patch below, but I'd really like some feedback on whether I've done something crazy here (or maybe there's a better way?). I've tested it using pre-allocate with priorities, and using normal allocation with priorities, and all seems to be fine. Here's a summary of what I did:
First, I added a new function in FileSelector to initialize the priority list. This function, initialize_priorities_now(), is a stripped down version of set_priorities_now(). It calls a new function, _initialize_disabled_files(), which is a stripped down version of _set_disabled_files(). The initialization then gets called from the initFiles() function of download_bt1 before the StorageWrapper initialization is called (which is where the allocation is done).
Next, I modified Storage to not write to files that are disabled. I did this by using the disabled_files return value from _get_disabled_files() as the working_range for disabled files. This only has the cached partial-begin and -end pieces for the disabled files (so the hash check will succeed), but not the main parts of the file. It's complicated a bit by the disabled_files return value not using the same format as the working_ranges, so I had to rearrange it in a few places.
Hopefully that makes some sense (or maybe I just muddied the waters more
). I'm happy to answer any questions, and please, give me feedback! Here's the patch:
Code:
Index: BitTornado/BT1/Storage.py
===================================================================
--- BitTornado/BT1/Storage.py (revision 98)
+++ BitTornado/BT1/Storage.py (working copy)
@@ -273,9 +273,10 @@
begin, end, offset, file = self.ranges[p]
if begin >= stop:
break
- r.append(( file,
- offset + max(pos, begin) - begin,
- offset + min(end, stop) - begin ))
+ if end > pos:
+ r.append(( file,
+ offset + max(pos, begin) - begin,
+ offset + min(end, stop) - begin ))
p += 1
return r
@@ -370,7 +371,7 @@
else:
midfile = os.path.join(self.bufferdir,str(f))
working_range = [(start, end, 0, midfile)]
- disabled_files.append((midfile, start, end))
+ disabled_files.append((start, end, 0, midfile))
length = end - start
self.sizes[midfile] = length
piece = pieces[0]
@@ -381,7 +382,7 @@
end_b = pieces[1]*self.piece_length
startfile = os.path.join(self.bufferdir,str(f)+'b')
working_range_b = [ ( start, end_b, 0, startfile ) ]
- disabled_files.append((startfile, start, end_b))
+ disabled_files.append((start, end_b, 0, startfile))
length = end_b - start
self.sizes[startfile] = length
offset = length
@@ -394,7 +395,7 @@
start_e = pieces[-1] * self.piece_length
endfile = os.path.join(self.bufferdir,str(f)+'e')
working_range_e = [ ( start_e, end, 0, endfile ) ]
- disabled_files.append((endfile, start_e, end))
+ disabled_files.append((start_e, end, 0, endfile))
length = end - start_e
self.sizes[endfile] = length
piece = pieces.pop(-1)
@@ -445,7 +446,7 @@
r = self._get_disabled_ranges(f)
if not r:
return
- for file, begin, end in r[2]:
+ for begin, end, offset, file in r[2]:
if not os.path.isdir(self.bufferdir):
os.makedirs(self.bufferdir)
if not exists(file):
@@ -456,7 +457,7 @@
self.tops[file] = getsize(file)
if not self.mtimes.has_key(file):
self.mtimes[file] = getmtime(file)
- self.working_ranges[f] = r[0]
+ self.working_ranges[f] = r[2]
reset_file_status = _reset_ranges
@@ -497,7 +498,7 @@
if not self.files[i][1]: # length == 0
continue
if self.disabled[i]:
- for file, start, end in self._get_disabled_ranges(i)[2]:
+ for start, end, offset, file in self._get_disabled_ranges(i)[2]:
pfiles.extend([basename(file),getsize(file),int(getmtime(file))])
continue
file = self.files[i][0]
@@ -550,7 +551,7 @@
for i in xrange(len(self.files)):
if self.disabled[i]:
- for file, start, end in self._get_disabled_ranges(i)[2]:
+ for start, end, offset, file in self._get_disabled_ranges(i)[2]:
f1 = basename(file)
if ( not pfiles.has_key(f1)
or not test(pfiles[f1],getsize(file),getmtime(file)) ):
Index: BitTornado/BT1/FileSelector.py
===================================================================
--- BitTornado/BT1/FileSelector.py (revision 98)
+++ BitTornado/BT1/FileSelector.py (working copy)
@@ -104,6 +104,30 @@
self.new_partials = None
+ def _initialize_files_disabled(self, old_priority, new_priority):
+ old_disabled = [p == -1 for p in old_priority]
+ new_disabled = [p == -1 for p in new_priority]
+ files_updated = False
+ try:
+ for f in xrange(self.numfiles):
+ if new_disabled[f] and not old_disabled[f]:
+ self.storage.disable_file(f)
+ files_updated = True
+ if old_disabled[f] and not new_disabled[f]:
+ self.storage.enable_file(f)
+ files_updated = True
+ except (IOError, OSError), e:
+ if new_disabled[f]:
+ msg = "can't open partial file for "
+ else:
+ msg = 'unable to open '
+ self.failfunc(msg + self.files[f][0] + ': ' + str(e))
+ return False
+ if files_updated:
+ self.storage.reset_file_status()
+ return True
+
+
def _set_files_disabled(self, old_priority, new_priority):
old_disabled = [p == -1 for p in old_priority]
new_disabled = [p == -1 for p in new_priority]
@@ -189,6 +213,15 @@
return new_piece_priority
+ def initialize_priorities_now(self, new_priority = None):
+ if not new_priority:
+ return
+ old_priority = self.priority
+ self.priority = new_priority
+ if not self._initialize_files_disabled(old_priority, new_priority):
+ return
+# self.piece_priority = self._set_piece_priority(new_priority)
+
def set_priorities_now(self, new_priority = None):
if not new_priority:
new_priority = self.new_priority
Index: BitTornado/download_bt1.py
===================================================================
--- BitTornado/download_bt1.py (revision 98)
+++ BitTornado/download_bt1.py (working copy)
@@ -544,6 +544,9 @@
data = data.get('resume data')
if data:
self.fileselector.unpickle(data)
+
+ if self.priority:
+ self.fileselector.initialize_priorities_now(self.priority)
self.checking = True
if old_style: