mirror of https://github.com/aria2/aria2
				
				
				
			2006-04-16 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
* src/TorrentConsoleDownloadEngine.cc (onPartialDownloadingCompletes): Renamed as onSelectiveDownloadingCompletes. (onSelectiveDownloadingCompletes): Updated message. To add DiskAdaptor which abstract DiskWriter family: * src/PeerConnection.cc: Use diskAdaptor instead of diskWriter. * src/PeerInteractionCommand.cc: Use diskAdaptor instead of diskWriter. * src/BitfieldMan.cc (isAllBitSet): bug fix. * src/TorrentMan.cc : Included CopyDiskAdaptor.h, DirectDiskAdaptor.h, MultiDiskAdaptor.h. (readFileEntry): Changed its arguments. (setup): setupDiskWriter is merged into this function. (setupDiskWriter): Removed. (setFileFilter): New function. (readFileEntryFromMetaInfoFile): Updated according to the changes made in readFileEntry. (getFilePath): Removed. (getTempFilePath): Removed. (getSegmentFilePath): Updated due to the removal of getFilePath. (fixFilename): Removed. (copySingleFile): Removed. (splitMultiFile): Removed. (deleteTempFile): Removed. (setFileEntriesToDownload): Removed. (isPartialDownloadingMode): Renamed as isSelectiveDownloadingMode. (isSelectiveDownloadingMode): New function. (setAllMultiFileRequestedState): Removed. (finishPartialDownloadingMode): Renamed as finishSelectiveDownloadingMode. (finishSelectiveDownloadingMode): New function. (getPartialTotalLength): Renamed as getSelectedTotalLength. (getSelectedTotalLength): New function. (onDownloadComplete): Use diskAdaptor. * src/MultiDiskWriter.cc (Constructor): Added the argument pieceLength (Range): Removed. (setMultiFileEntries): Renamed as setFileEntries. (setFileEntries): New function. * src/MultiDiskWriter.h [DiskWriterEntry](enabled): Removed. (pieceLength): New variable. * src/main.cc (printDownloadCompeleteMessage): New function. (torrentHandler): Use diskAdaptor instead of diskWriter. (main): Renamed torrent-show-files to show-files. Rewritten file contents listing. * src/TorrentMan.h (FileEntry): Removed. (multiFileTopDir): Removed. (multiFileEntries): Removed. (diskWriter): Removed. (diskAdaptor): New variable. * src/DefaultDiskWriter.h (totalLength): New variable. * src/DefaultDiskWriter.cc (initAndOpenFile): Added ftruncate. * src/TorrentDownloadEngine.cc (onEndOfRun): Use diskAdaptor instead of diskWriter. * src/TorrentConsoleDownloadEngine.h (partialDownloadLengthDiff): Renamed as selectedDownloadLengthDiff. (partialTotalLength): Renamed as selectedTotalLength. * src/AbstractDiskWriter.cc (openFile): If file exists, call openExistingFile, otherwise call initAndOpenFile. (closeFile): fd > 0, not fd != 0. * src/prefs.h (PREF_TORRENT_SHOW_FILES): Renamed as PREF_SHOW_FILES (PREF_SHOW_FILES): New definition.pull/1/head
							parent
							
								
									58633887e9
								
							
						
					
					
						commit
						2a84b9de43
					
				
							
								
								
									
										68
									
								
								ChangeLog
								
								
								
								
							
							
						
						
									
										68
									
								
								ChangeLog
								
								
								
								
							| 
						 | 
				
			
			@ -1,3 +1,71 @@
 | 
			
		|||
2006-04-16  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 | 
			
		||||
 | 
			
		||||
	* src/TorrentConsoleDownloadEngine.cc
 | 
			
		||||
	(onPartialDownloadingCompletes): Renamed as
 | 
			
		||||
	onSelectiveDownloadingCompletes.
 | 
			
		||||
	(onSelectiveDownloadingCompletes): Updated message.
 | 
			
		||||
 | 
			
		||||
	To add DiskAdaptor which abstract DiskWriter family:
 | 
			
		||||
 | 
			
		||||
	* src/PeerConnection.cc: Use diskAdaptor instead of diskWriter.
 | 
			
		||||
	* src/PeerInteractionCommand.cc: Use diskAdaptor instead of diskWriter.
 | 
			
		||||
	* src/BitfieldMan.cc (isAllBitSet): bug fix.
 | 
			
		||||
	* src/TorrentMan.cc : Included CopyDiskAdaptor.h, DirectDiskAdaptor.h,
 | 
			
		||||
	MultiDiskAdaptor.h.
 | 
			
		||||
	(readFileEntry): Changed its arguments.
 | 
			
		||||
	(setup): setupDiskWriter is merged into this function.
 | 
			
		||||
	(setupDiskWriter): Removed.
 | 
			
		||||
	(setFileFilter): New function.
 | 
			
		||||
	(readFileEntryFromMetaInfoFile): Updated according to the changes
 | 
			
		||||
	made in readFileEntry.
 | 
			
		||||
	(getFilePath): Removed.
 | 
			
		||||
	(getTempFilePath): Removed.
 | 
			
		||||
	(getSegmentFilePath): Updated due to the removal of getFilePath.
 | 
			
		||||
	(fixFilename): Removed.
 | 
			
		||||
	(copySingleFile): Removed.
 | 
			
		||||
	(splitMultiFile): Removed.
 | 
			
		||||
	(deleteTempFile): Removed.
 | 
			
		||||
	(setFileEntriesToDownload): Removed.
 | 
			
		||||
	(isPartialDownloadingMode): Renamed as isSelectiveDownloadingMode.
 | 
			
		||||
	(isSelectiveDownloadingMode): New function.
 | 
			
		||||
	(setAllMultiFileRequestedState): Removed.
 | 
			
		||||
	(finishPartialDownloadingMode): Renamed as
 | 
			
		||||
	finishSelectiveDownloadingMode.
 | 
			
		||||
	(finishSelectiveDownloadingMode): New function.
 | 
			
		||||
	(getPartialTotalLength): Renamed as getSelectedTotalLength.
 | 
			
		||||
	(getSelectedTotalLength): New function.
 | 
			
		||||
	(onDownloadComplete): Use diskAdaptor.
 | 
			
		||||
	* src/MultiDiskWriter.cc (Constructor): Added the argument pieceLength
 | 
			
		||||
	(Range): Removed.
 | 
			
		||||
	(setMultiFileEntries): Renamed as setFileEntries.
 | 
			
		||||
	(setFileEntries): New function.
 | 
			
		||||
	* src/MultiDiskWriter.h [DiskWriterEntry](enabled): Removed.
 | 
			
		||||
	(pieceLength): New variable.
 | 
			
		||||
	* src/main.cc (printDownloadCompeleteMessage): New function.
 | 
			
		||||
	(torrentHandler): Use diskAdaptor instead of diskWriter.
 | 
			
		||||
	(main): Renamed torrent-show-files to show-files.
 | 
			
		||||
	Rewritten file contents listing.
 | 
			
		||||
	* src/TorrentMan.h (FileEntry): Removed.
 | 
			
		||||
	(multiFileTopDir): Removed.
 | 
			
		||||
	(multiFileEntries): Removed.
 | 
			
		||||
	(diskWriter): Removed.
 | 
			
		||||
	(diskAdaptor): New variable.
 | 
			
		||||
	* src/DefaultDiskWriter.h (totalLength): New variable.
 | 
			
		||||
	* src/DefaultDiskWriter.cc (initAndOpenFile): Added ftruncate.
 | 
			
		||||
	* src/TorrentDownloadEngine.cc (onEndOfRun): Use diskAdaptor instead of
 | 
			
		||||
	diskWriter.
 | 
			
		||||
	* src/TorrentConsoleDownloadEngine.h
 | 
			
		||||
	(partialDownloadLengthDiff): Renamed as selectedDownloadLengthDiff.
 | 
			
		||||
	(partialTotalLength): Renamed as selectedTotalLength.
 | 
			
		||||
	* src/AbstractDiskWriter.cc (openFile): If file exists, call
 | 
			
		||||
	openExistingFile, otherwise call initAndOpenFile.
 | 
			
		||||
	(closeFile): fd > 0, not fd != 0.
 | 
			
		||||
	
 | 
			
		||||
	* src/prefs.h (PREF_TORRENT_SHOW_FILES): Renamed as PREF_SHOW_FILES
 | 
			
		||||
	(PREF_SHOW_FILES): New definition.
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
2006-04-12  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 | 
			
		||||
 | 
			
		||||
	To add the ability to download multi torrent into respective files
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										12
									
								
								TODO
								
								
								
								
							
							
						
						
									
										12
									
								
								TODO
								
								
								
								
							| 
						 | 
				
			
			@ -11,6 +11,14 @@
 | 
			
		|||
* Add port range command-line option
 | 
			
		||||
* Add max peers command-line option
 | 
			
		||||
* Distinguish seeder from leecher
 | 
			
		||||
* file selection in multi-file mode
 | 
			
		||||
 | 
			
		||||
0.4.0 release
 | 
			
		||||
* Add selective downloading mode
 | 
			
		||||
* try to use ftruncate to allocate file.
 | 
			
		||||
* fix TorrentMan::getFilePath()
 | 
			
		||||
* test all download mode
 | 
			
		||||
* Add loggerfactory
 | 
			
		||||
* Add SIGTERM signal handler
 | 
			
		||||
 | 
			
		||||
0.4.1 release
 | 
			
		||||
* Add port command-line option
 | 
			
		||||
* Add estimated remaining time to normal HTTP/FTP downloading status ouput
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,7 +36,7 @@ AbstractDiskWriter::AbstractDiskWriter():fd(0) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
AbstractDiskWriter::~AbstractDiskWriter() {
 | 
			
		||||
  if(fd != 0) {
 | 
			
		||||
  if(fd > 0) {
 | 
			
		||||
    close(fd);
 | 
			
		||||
  }
 | 
			
		||||
#ifdef ENABLE_SHA1DIGEST
 | 
			
		||||
| 
						 | 
				
			
			@ -45,13 +45,16 @@ AbstractDiskWriter::~AbstractDiskWriter() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void AbstractDiskWriter::openFile(const string& filename) {
 | 
			
		||||
  if((fd = open(filename.c_str(), O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0) {
 | 
			
		||||
    throw new DlAbortEx(strerror(errno));
 | 
			
		||||
  File f(filename);
 | 
			
		||||
  if(f.exists()) {
 | 
			
		||||
    openExistingFile(filename);
 | 
			
		||||
  } else {
 | 
			
		||||
    initAndOpenFile(filename);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AbstractDiskWriter::closeFile() {
 | 
			
		||||
  if(fd != 0) {
 | 
			
		||||
  if(fd > 0) {
 | 
			
		||||
    close(fd);
 | 
			
		||||
    fd = 0;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -261,7 +261,7 @@ bool BitfieldMan::unsetBit(int index) {
 | 
			
		|||
 | 
			
		||||
bool BitfieldMan::isAllBitSet() const {
 | 
			
		||||
  if(filterEnabled) {
 | 
			
		||||
    for(int i = 0; i < bitfieldLength-1; i++) {
 | 
			
		||||
    for(int i = 0; i < bitfieldLength; i++) {
 | 
			
		||||
      if((bitfield[i]&filterBitfield[i]) != filterBitfield[i]) {
 | 
			
		||||
	return false;
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,10 +23,15 @@
 | 
			
		|||
#include "DlAbortEx.h"
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
DefaultDiskWriter::DefaultDiskWriter():AbstractDiskWriter() {}
 | 
			
		||||
DefaultDiskWriter::DefaultDiskWriter():AbstractDiskWriter(), totalLength(0) {}
 | 
			
		||||
 | 
			
		||||
DefaultDiskWriter::DefaultDiskWriter(long long int totalLength):AbstractDiskWriter(), totalLength(totalLength) {}
 | 
			
		||||
 | 
			
		||||
DefaultDiskWriter::~DefaultDiskWriter() {}
 | 
			
		||||
 | 
			
		||||
void DefaultDiskWriter::initAndOpenFile(string filename) {
 | 
			
		||||
  createFile(filename);
 | 
			
		||||
  if(totalLength > 0) {
 | 
			
		||||
    ftruncate(fd, totalLength);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,8 +25,11 @@
 | 
			
		|||
#include "AbstractDiskWriter.h"
 | 
			
		||||
 | 
			
		||||
class DefaultDiskWriter:public AbstractDiskWriter {
 | 
			
		||||
private:
 | 
			
		||||
  long long int totalLength;
 | 
			
		||||
public:
 | 
			
		||||
  DefaultDiskWriter();
 | 
			
		||||
  DefaultDiskWriter(long long int totalLength);
 | 
			
		||||
  ~DefaultDiskWriter();
 | 
			
		||||
 | 
			
		||||
  void initAndOpenFile(string filename);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,42 @@
 | 
			
		|||
/* <!-- copyright */
 | 
			
		||||
/*
 | 
			
		||||
 * aria2 - a simple utility for downloading files faster
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2006 Tatsuhiro Tsujikawa
 | 
			
		||||
 *
 | 
			
		||||
 * 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 of the License, 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
 | 
			
		||||
 */
 | 
			
		||||
/* copyright --> */
 | 
			
		||||
#ifndef _D_FILE_ENTRY_H_
 | 
			
		||||
#define _D_FILE_ENTRY_H_
 | 
			
		||||
 | 
			
		||||
#include "common.h"
 | 
			
		||||
 | 
			
		||||
class FileEntry {
 | 
			
		||||
public:
 | 
			
		||||
  string path;
 | 
			
		||||
  long long int length;
 | 
			
		||||
  long long int offset;
 | 
			
		||||
  bool extracted;
 | 
			
		||||
  bool requested;
 | 
			
		||||
  FileEntry(string path, long long int length, long long int offset):
 | 
			
		||||
    path(path), length(length), offset(offset),
 | 
			
		||||
    extracted(false), requested(true) {}
 | 
			
		||||
  ~FileEntry() {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef deque<FileEntry> FileEntries;
 | 
			
		||||
 | 
			
		||||
#endif // _D_FILE_ENTRY_H_
 | 
			
		||||
| 
						 | 
				
			
			@ -79,7 +79,12 @@ SRCS =  Socket.cc Socket.h\
 | 
			
		|||
	TrackerWatcherCommand.cc TrackerWatcherCommand.h\
 | 
			
		||||
	messageDigest.h\
 | 
			
		||||
	SendMessageQueue.cc SendMessageQueue.h\
 | 
			
		||||
	MultiDiskWriter.cc MultiDiskWriter.h
 | 
			
		||||
	MultiDiskWriter.cc MultiDiskWriter.h\
 | 
			
		||||
	DiskAdaptor.cc DiskAdaptor.h\
 | 
			
		||||
	CopyDiskAdaptor.cc CopyDiskAdaptor.h\
 | 
			
		||||
	DirectDiskAdaptor.cc DirectDiskAdaptor.h\
 | 
			
		||||
	MultiDiskAdaptor.cc MultiDiskAdaptor.h\
 | 
			
		||||
	FileEntry.h
 | 
			
		||||
noinst_LIBRARIES = libaria2c.a
 | 
			
		||||
libaria2c_a_SOURCES = $(SRCS)
 | 
			
		||||
aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -98,7 +98,9 @@ am__objects_1 = Socket.$(OBJEXT) SocketCore.$(OBJEXT) \
 | 
			
		|||
	PeerMessage.$(OBJEXT) Piece.$(OBJEXT) RequestSlot.$(OBJEXT) \
 | 
			
		||||
	RequestSlotMan.$(OBJEXT) TorrentAutoSaveCommand.$(OBJEXT) \
 | 
			
		||||
	Directory.$(OBJEXT) TrackerWatcherCommand.$(OBJEXT) \
 | 
			
		||||
	SendMessageQueue.$(OBJEXT) MultiDiskWriter.$(OBJEXT)
 | 
			
		||||
	SendMessageQueue.$(OBJEXT) MultiDiskWriter.$(OBJEXT) \
 | 
			
		||||
	DiskAdaptor.$(OBJEXT) CopyDiskAdaptor.$(OBJEXT) \
 | 
			
		||||
	DirectDiskAdaptor.$(OBJEXT) MultiDiskAdaptor.$(OBJEXT)
 | 
			
		||||
am_libaria2c_a_OBJECTS = $(am__objects_1)
 | 
			
		||||
libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS)
 | 
			
		||||
am__installdirs = "$(DESTDIR)$(bindir)"
 | 
			
		||||
| 
						 | 
				
			
			@ -327,7 +329,12 @@ SRCS = Socket.cc Socket.h\
 | 
			
		|||
	TrackerWatcherCommand.cc TrackerWatcherCommand.h\
 | 
			
		||||
	messageDigest.h\
 | 
			
		||||
	SendMessageQueue.cc SendMessageQueue.h\
 | 
			
		||||
	MultiDiskWriter.cc MultiDiskWriter.h
 | 
			
		||||
	MultiDiskWriter.cc MultiDiskWriter.h\
 | 
			
		||||
	DiskAdaptor.cc DiskAdaptor.h\
 | 
			
		||||
	CopyDiskAdaptor.cc CopyDiskAdaptor.h\
 | 
			
		||||
	DirectDiskAdaptor.cc DirectDiskAdaptor.h\
 | 
			
		||||
	MultiDiskAdaptor.cc MultiDiskAdaptor.h\
 | 
			
		||||
	FileEntry.h
 | 
			
		||||
 | 
			
		||||
noinst_LIBRARIES = libaria2c.a
 | 
			
		||||
libaria2c_a_SOURCES = $(SRCS)
 | 
			
		||||
| 
						 | 
				
			
			@ -420,10 +427,13 @@ distclean-compile:
 | 
			
		|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChunkedEncoding.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ConsoleDownloadEngine.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieBox.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CopyDiskAdaptor.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Data.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultDiskWriter.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Dictionary.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DirectDiskAdaptor.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Directory.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DiskAdaptor.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadCommand.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadEngine.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/File.Po@am__quote@
 | 
			
		||||
| 
						 | 
				
			
			@ -444,6 +454,7 @@ distclean-compile:
 | 
			
		|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/InitiateConnectionCommandFactory.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/List.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetaFileUtil.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MultiDiskAdaptor.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MultiDiskWriter.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Option.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Peer.Po@am__quote@
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,7 +24,7 @@
 | 
			
		|||
#include "Util.h"
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
MultiDiskWriter::MultiDiskWriter() {
 | 
			
		||||
MultiDiskWriter::MultiDiskWriter(int pieceLength):pieceLength(pieceLength) {
 | 
			
		||||
#ifdef ENABLE_SHA1DIGEST
 | 
			
		||||
  sha1DigestInit(ctx);
 | 
			
		||||
#endif // ENABLE_SHA1DIGEST
 | 
			
		||||
| 
						 | 
				
			
			@ -37,63 +37,26 @@ MultiDiskWriter::~MultiDiskWriter() {
 | 
			
		|||
#endif // ENABLE_SHA1DIGEST
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  long long int blockOffset;
 | 
			
		||||
  long long int length;
 | 
			
		||||
} Range;
 | 
			
		||||
 | 
			
		||||
typedef deque<Range> Ranges;
 | 
			
		||||
 | 
			
		||||
void MultiDiskWriter::clearEntries() {
 | 
			
		||||
  for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
 | 
			
		||||
      itr != diskWriterEntries.end(); itr++) {
 | 
			
		||||
    if((*itr)->enabled) {
 | 
			
		||||
      (*itr)->diskWriter->closeFile();
 | 
			
		||||
    }
 | 
			
		||||
    delete *itr;
 | 
			
		||||
  }
 | 
			
		||||
  diskWriterEntries.clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MultiDiskWriter::setMultiFileEntries(const MultiFileEntries& multiFileEntries, int pieceLength) {
 | 
			
		||||
void MultiDiskWriter::setFileEntries(const FileEntries& fileEntries) {
 | 
			
		||||
  clearEntries();
 | 
			
		||||
  Ranges ranges;
 | 
			
		||||
  for(MultiFileEntries::const_iterator itr = multiFileEntries.begin();
 | 
			
		||||
      itr != multiFileEntries.end(); itr++) {
 | 
			
		||||
    if(itr->requested) {
 | 
			
		||||
      Range range;
 | 
			
		||||
      range.blockOffset = (itr->offset/pieceLength)*pieceLength;
 | 
			
		||||
      range.length = ((itr->offset+itr->length)/pieceLength+
 | 
			
		||||
	((itr->offset+itr->length)%pieceLength ? 1 : 0))*pieceLength-range.blockOffset;
 | 
			
		||||
      ranges.push_back(range);
 | 
			
		||||
    }		
 | 
			
		||||
  }
 | 
			
		||||
  Ranges::const_iterator ritr = ranges.begin();
 | 
			
		||||
  for(MultiFileEntries::const_iterator itr = multiFileEntries.begin();
 | 
			
		||||
      itr != multiFileEntries.end(); itr++) {
 | 
			
		||||
    DiskWriterEntry* entry;
 | 
			
		||||
    if(ritr != ranges.end() &&
 | 
			
		||||
       //       !(ritr->blockOffset+ritr->length-1 < itr->offset ||
 | 
			
		||||
       //	 itr->offset+itr->length-1 < ritr->blockOffset)) {
 | 
			
		||||
       itr->offset < ritr->blockOffset+ritr->length &&
 | 
			
		||||
       ritr->blockOffset < itr->offset+itr->length) {
 | 
			
		||||
 | 
			
		||||
      entry = new DiskWriterEntry(*itr, true);
 | 
			
		||||
      for(;ritr->blockOffset+ritr->length <= itr->offset+itr->length &&
 | 
			
		||||
	    ritr != ranges.end(); ritr++);
 | 
			
		||||
    } else {
 | 
			
		||||
      entry = new DiskWriterEntry(*itr, false);
 | 
			
		||||
    }
 | 
			
		||||
    diskWriterEntries.push_back(entry);
 | 
			
		||||
  for(FileEntries::const_iterator itr = fileEntries.begin();
 | 
			
		||||
      itr != fileEntries.end(); itr++) {
 | 
			
		||||
    diskWriterEntries.push_back(new DiskWriterEntry(*itr));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MultiDiskWriter::openFile(const string& filename) {
 | 
			
		||||
  for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
 | 
			
		||||
      itr != diskWriterEntries.end(); itr++) {
 | 
			
		||||
    if((*itr)->enabled) {
 | 
			
		||||
      (*itr)->diskWriter->openFile(filename+"/"+(*itr)->fileEntry.path);
 | 
			
		||||
    }
 | 
			
		||||
    (*itr)->diskWriter->openFile(filename+"/"+(*itr)->fileEntry.path);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -101,27 +64,21 @@ void MultiDiskWriter::openFile(const string& filename) {
 | 
			
		|||
void MultiDiskWriter::initAndOpenFile(string filename) {
 | 
			
		||||
  for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
 | 
			
		||||
      itr != diskWriterEntries.end(); itr++) {
 | 
			
		||||
    if((*itr)->enabled) {
 | 
			
		||||
      (*itr)->diskWriter->initAndOpenFile(filename+"/"+(*itr)->fileEntry.path);
 | 
			
		||||
    }
 | 
			
		||||
    (*itr)->diskWriter->initAndOpenFile(filename+"/"+(*itr)->fileEntry.path);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MultiDiskWriter::closeFile() {
 | 
			
		||||
  for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
 | 
			
		||||
      itr != diskWriterEntries.end(); itr++) {
 | 
			
		||||
    if((*itr)->enabled) {
 | 
			
		||||
      (*itr)->diskWriter->closeFile();
 | 
			
		||||
    }
 | 
			
		||||
    (*itr)->diskWriter->closeFile();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MultiDiskWriter::openExistingFile(string filename) {
 | 
			
		||||
  for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
 | 
			
		||||
      itr != diskWriterEntries.end(); itr++) {
 | 
			
		||||
    if((*itr)->enabled) {
 | 
			
		||||
      (*itr)->diskWriter->openExistingFile(filename+"/"+(*itr)->fileEntry.path);
 | 
			
		||||
    }
 | 
			
		||||
    (*itr)->diskWriter->openExistingFile(filename+"/"+(*itr)->fileEntry.path);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -133,9 +90,6 @@ void MultiDiskWriter::writeData(const char* data, int len, long long int positio
 | 
			
		|||
  for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
 | 
			
		||||
      itr != diskWriterEntries.end() && rem != 0; itr++) {
 | 
			
		||||
    if(isInRange(*itr, offset) || writing) {
 | 
			
		||||
      if(!(*itr)->enabled) {
 | 
			
		||||
	throw new DlAbortEx("invalid offset or length. offset = %lld", offset);
 | 
			
		||||
      }
 | 
			
		||||
      int writeLength = calculateLength(*itr, fileOffset, rem);
 | 
			
		||||
      (*itr)->diskWriter->writeData(data+(len-rem), writeLength, fileOffset);
 | 
			
		||||
      rem -= writeLength;
 | 
			
		||||
| 
						 | 
				
			
			@ -174,9 +128,6 @@ int MultiDiskWriter::readData(char* data, int len, long long int position) {
 | 
			
		|||
  for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
 | 
			
		||||
      itr != diskWriterEntries.end() && rem != 0; itr++) {
 | 
			
		||||
    if(isInRange(*itr, offset) || reading) {
 | 
			
		||||
      if(!(*itr)->enabled) {
 | 
			
		||||
	throw new DlAbortEx("invalid offset or length. offset = %lld", offset);
 | 
			
		||||
      }
 | 
			
		||||
      int readLength = calculateLength((*itr), fileOffset, rem);
 | 
			
		||||
      totalReadLength += (*itr)->diskWriter->readData(data+(len-rem), readLength, fileOffset);
 | 
			
		||||
      rem -= readLength;
 | 
			
		||||
| 
						 | 
				
			
			@ -223,9 +174,6 @@ string MultiDiskWriter::sha1Sum(long long int offset, long long int length) {
 | 
			
		|||
    for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
 | 
			
		||||
	itr != diskWriterEntries.end() && rem != 0; itr++) {
 | 
			
		||||
      if(isInRange(*itr, offset) || reading) {
 | 
			
		||||
	if(!(*itr)->enabled) {
 | 
			
		||||
	  throw new DlAbortEx("invalid offset or length. offset = %lld", offset);
 | 
			
		||||
	}
 | 
			
		||||
	int readLength = calculateLength((*itr), fileOffset, rem);
 | 
			
		||||
	hashUpdate(*itr, fileOffset, readLength);
 | 
			
		||||
	rem -= readLength;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,17 +30,12 @@ class DiskWriterEntry {
 | 
			
		|||
public:
 | 
			
		||||
  FileEntry fileEntry;
 | 
			
		||||
  DiskWriter* diskWriter;
 | 
			
		||||
  bool enabled;
 | 
			
		||||
public:
 | 
			
		||||
  DiskWriterEntry(const FileEntry& fileEntry, bool enabled):fileEntry(fileEntry), enabled(enabled) {
 | 
			
		||||
    if(enabled) {
 | 
			
		||||
      diskWriter = new DefaultDiskWriter();
 | 
			
		||||
    }
 | 
			
		||||
  DiskWriterEntry(const FileEntry& fileEntry):fileEntry(fileEntry) {
 | 
			
		||||
    diskWriter = new DefaultDiskWriter(this->fileEntry.length);
 | 
			
		||||
  }
 | 
			
		||||
  ~DiskWriterEntry() {
 | 
			
		||||
    if(enabled) {
 | 
			
		||||
      delete diskWriter;
 | 
			
		||||
    }
 | 
			
		||||
    delete diskWriter;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -49,7 +44,7 @@ typedef deque<DiskWriterEntry*> DiskWriterEntries;
 | 
			
		|||
class MultiDiskWriter : public DiskWriter {
 | 
			
		||||
private:
 | 
			
		||||
  DiskWriterEntries diskWriterEntries;
 | 
			
		||||
 | 
			
		||||
  int pieceLength;
 | 
			
		||||
  bool isInRange(const DiskWriterEntry* entry, long long int offset) const;
 | 
			
		||||
  int calculateLength(const DiskWriterEntry* entry, long long int fileOffset, int rem) const;
 | 
			
		||||
  void clearEntries();
 | 
			
		||||
| 
						 | 
				
			
			@ -59,10 +54,10 @@ private:
 | 
			
		|||
#endif // ENABLE_SHA1DIGEST
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  MultiDiskWriter();
 | 
			
		||||
  MultiDiskWriter(int pieceLength);
 | 
			
		||||
  virtual ~MultiDiskWriter();
 | 
			
		||||
 | 
			
		||||
  void setMultiFileEntries(const MultiFileEntries& multiFileEntries, int pieceLength);
 | 
			
		||||
  void setFileEntries(const FileEntries& fileEntries);
 | 
			
		||||
 | 
			
		||||
  virtual void openFile(const string& filename);
 | 
			
		||||
  virtual void initAndOpenFile(string filename);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -216,14 +216,14 @@ void PeerConnection::sendPiece(int index, int begin, int length) const {
 | 
			
		|||
  int iteration = length/BUF_SIZE;
 | 
			
		||||
  long long int pieceOffset = ((long long int)index*torrentMan->pieceLength)+begin;
 | 
			
		||||
  for(int i = 0; i < iteration; i++) {
 | 
			
		||||
    if(torrentMan->diskWriter->readData(buf, BUF_SIZE, pieceOffset+i*BUF_SIZE) < BUF_SIZE) {
 | 
			
		||||
    if(torrentMan->diskAdaptor->readData(buf, BUF_SIZE, pieceOffset+i*BUF_SIZE) < BUF_SIZE) {
 | 
			
		||||
      throw new DlAbortEx("piece reading failed.");
 | 
			
		||||
    }
 | 
			
		||||
    socket->writeData(buf, BUF_SIZE);
 | 
			
		||||
  }
 | 
			
		||||
  int rem = length%BUF_SIZE;
 | 
			
		||||
  if(rem > 0) {
 | 
			
		||||
    if(torrentMan->diskWriter->readData(buf, rem, pieceOffset+iteration*BUF_SIZE) < rem) {
 | 
			
		||||
    if(torrentMan->diskAdaptor->readData(buf, rem, pieceOffset+iteration*BUF_SIZE) < rem) {
 | 
			
		||||
      throw new DlAbortEx("piece reading failed.");
 | 
			
		||||
    }
 | 
			
		||||
    socket->writeData(buf, rem);
 | 
			
		||||
| 
						 | 
				
			
			@ -259,7 +259,7 @@ int PeerConnection::sendPieceData(long long int offset, int length) const {
 | 
			
		|||
    if(!isWritable) {
 | 
			
		||||
      return writtenLength;
 | 
			
		||||
    }
 | 
			
		||||
    if(torrentMan->diskWriter->readData(buf, BUF_SIZE, offset+i*BUF_SIZE) < BUF_SIZE) {
 | 
			
		||||
    if(torrentMan->diskAdaptor->readData(buf, BUF_SIZE, offset+i*BUF_SIZE) < BUF_SIZE) {
 | 
			
		||||
      throw new DlAbortEx("piece reading failed.");
 | 
			
		||||
    }
 | 
			
		||||
    socket->writeData(buf, BUF_SIZE);
 | 
			
		||||
| 
						 | 
				
			
			@ -268,7 +268,7 @@ int PeerConnection::sendPieceData(long long int offset, int length) const {
 | 
			
		|||
  if(socket->isWritable(0)) {
 | 
			
		||||
    int rem = length%BUF_SIZE;
 | 
			
		||||
    if(rem > 0) {
 | 
			
		||||
      if(torrentMan->diskWriter->readData(buf, rem, offset+iteration*BUF_SIZE) < rem) {
 | 
			
		||||
      if(torrentMan->diskAdaptor->readData(buf, rem, offset+iteration*BUF_SIZE) < rem) {
 | 
			
		||||
	throw new DlAbortEx("piece reading failed.");
 | 
			
		||||
      }
 | 
			
		||||
      socket->writeData(buf, rem);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -274,9 +274,9 @@ void PeerInteractionCommand::receiveMessage() {
 | 
			
		|||
	  ((long long int)message->getIndex())*e->torrentMan->pieceLength+message->getBegin();
 | 
			
		||||
	e->logger->debug("CUID#%d - write block length = %d, offset=%lld",
 | 
			
		||||
			 cuid, message->getBlockLength(), offset);      
 | 
			
		||||
	e->torrentMan->diskWriter->writeData(message->getBlock(),
 | 
			
		||||
					     message->getBlockLength(),
 | 
			
		||||
					     offset);
 | 
			
		||||
	e->torrentMan->diskAdaptor->writeData(message->getBlock(),
 | 
			
		||||
					      message->getBlockLength(),
 | 
			
		||||
					      offset);
 | 
			
		||||
	piece.completeBlock(slot.getBlockIndex());
 | 
			
		||||
	sendMessageQueue->deleteRequestSlot(slot);
 | 
			
		||||
	e->torrentMan->updatePiece(piece);
 | 
			
		||||
| 
						 | 
				
			
			@ -444,7 +444,7 @@ void PeerInteractionCommand::beforeSocketCheck() {
 | 
			
		|||
 | 
			
		||||
bool PeerInteractionCommand::checkPieceHash(const Piece& piece) {
 | 
			
		||||
  long long int offset = ((long long int)piece.getIndex())*e->torrentMan->pieceLength;
 | 
			
		||||
  return e->torrentMan->diskWriter->sha1Sum(offset, piece.getLength()) ==
 | 
			
		||||
  return e->torrentMan->diskAdaptor->sha1Sum(offset, piece.getLength()) ==
 | 
			
		||||
    e->torrentMan->getPieceHash(piece.getIndex());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -454,11 +454,11 @@ void PeerInteractionCommand::erasePieceOnDisk(const Piece& piece) {
 | 
			
		|||
  memset(buf, 0, BUFSIZE);
 | 
			
		||||
  long long int offset = ((long long int)piece.getIndex())*e->torrentMan->pieceLength;
 | 
			
		||||
  for(int i = 0; i < piece.getLength()/BUFSIZE; i++) {
 | 
			
		||||
    e->torrentMan->diskWriter->writeData(buf, BUFSIZE, offset);
 | 
			
		||||
    e->torrentMan->diskAdaptor->writeData(buf, BUFSIZE, offset);
 | 
			
		||||
    offset += BUFSIZE;
 | 
			
		||||
  }
 | 
			
		||||
  int r = piece.getLength()%BUFSIZE;
 | 
			
		||||
  if(r > 0) {
 | 
			
		||||
    e->torrentMan->diskWriter->writeData(buf, r, offset);
 | 
			
		||||
    e->torrentMan->diskAdaptor->writeData(buf, r, offset);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,7 +35,6 @@ PreAllocationDiskWriter::~PreAllocationDiskWriter() {}
 | 
			
		|||
 | 
			
		||||
void PreAllocationDiskWriter::initAndOpenFile(string filename) {
 | 
			
		||||
  createFile(filename);
 | 
			
		||||
  
 | 
			
		||||
  int bufSize = 4096;
 | 
			
		||||
  char buf[4096];
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,8 +26,9 @@ TorrentConsoleDownloadEngine::TorrentConsoleDownloadEngine() {}
 | 
			
		|||
 | 
			
		||||
TorrentConsoleDownloadEngine::~TorrentConsoleDownloadEngine() {}
 | 
			
		||||
 | 
			
		||||
void TorrentConsoleDownloadEngine::onPartialDownloadingCompletes() {
 | 
			
		||||
  printf("Download of specified files has completed. Continue normal download operation.\n");
 | 
			
		||||
void TorrentConsoleDownloadEngine::onSelectiveDownloadingCompletes() {
 | 
			
		||||
  printf("\nDownload of selected files has completed.\n");
 | 
			
		||||
  fflush(stdout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TorrentConsoleDownloadEngine::printStatistics() {
 | 
			
		||||
| 
						 | 
				
			
			@ -68,9 +69,9 @@ void TorrentConsoleDownloadEngine::initStatistics() {
 | 
			
		|||
  sessionDownloadLength = 0;
 | 
			
		||||
  downloadLength = 0;
 | 
			
		||||
  totalLength = 0;
 | 
			
		||||
  if(torrentMan->isPartialDownloadingMode()) {
 | 
			
		||||
    partialDownloadLengthDiff = torrentMan->getDownloadLength()-torrentMan->getCompletedLength();
 | 
			
		||||
    partialTotalLength = torrentMan->getPartialTotalLength();
 | 
			
		||||
  if(torrentMan->isSelectiveDownloadingMode()) {
 | 
			
		||||
    selectedDownloadLengthDiff = torrentMan->getDownloadLength()-torrentMan->getCompletedLength();
 | 
			
		||||
    selectedTotalLength = torrentMan->getSelectedTotalLength();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -95,9 +96,9 @@ void TorrentConsoleDownloadEngine::calculateStatistics() {
 | 
			
		|||
  torrentMan->resetDeltaDownloadLength();
 | 
			
		||||
  torrentMan->resetDeltaUploadLength();
 | 
			
		||||
 | 
			
		||||
  if(torrentMan->isPartialDownloadingMode()) {
 | 
			
		||||
    downloadLength = torrentMan->getDownloadLength()-partialDownloadLengthDiff;
 | 
			
		||||
    totalLength = partialTotalLength;
 | 
			
		||||
  if(torrentMan->isSelectiveDownloadingMode()) {
 | 
			
		||||
    downloadLength = torrentMan->getDownloadLength()-selectedDownloadLengthDiff;
 | 
			
		||||
    totalLength = selectedTotalLength;
 | 
			
		||||
  } else {
 | 
			
		||||
    downloadLength = torrentMan->getDownloadLength();
 | 
			
		||||
    totalLength = torrentMan->getTotalLength();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,11 +26,6 @@
 | 
			
		|||
 | 
			
		||||
class TorrentConsoleDownloadEngine : public TorrentDownloadEngine {
 | 
			
		||||
private:
 | 
			
		||||
  /*
 | 
			
		||||
  struct timeval cp;
 | 
			
		||||
  long long int sessionDownloadSize;
 | 
			
		||||
  long long int sessionUploadSize;
 | 
			
		||||
  */
 | 
			
		||||
  struct timeval cp[2];
 | 
			
		||||
  long long int sessionDownloadLengthArray[2];
 | 
			
		||||
  long long int sessionUploadLengthArray[2];
 | 
			
		||||
| 
						 | 
				
			
			@ -39,11 +34,15 @@ private:
 | 
			
		|||
  int downloadSpeed;
 | 
			
		||||
  int uploadSpeed;
 | 
			
		||||
  int lastElapsed;
 | 
			
		||||
  long long int partialDownloadLengthDiff;
 | 
			
		||||
  long long int partialTotalLength;
 | 
			
		||||
  long long int selectedDownloadLengthDiff;
 | 
			
		||||
  long long int selectedTotalLength;
 | 
			
		||||
  // The time when startup
 | 
			
		||||
  struct timeval startup;
 | 
			
		||||
  // The number of bytes downloaded since startup
 | 
			
		||||
  long long int sessionDownloadLength;
 | 
			
		||||
  // The average speed(bytes per second) since startup
 | 
			
		||||
  int avgSpeed;
 | 
			
		||||
  // The estimated remaining time to complete the download.
 | 
			
		||||
  int eta;
 | 
			
		||||
  long long int downloadLength;
 | 
			
		||||
  long long int totalLength;
 | 
			
		||||
| 
						 | 
				
			
			@ -53,7 +52,7 @@ private:
 | 
			
		|||
protected:
 | 
			
		||||
  void initStatistics();
 | 
			
		||||
  void calculateStatistics();
 | 
			
		||||
  void onPartialDownloadingCompletes();
 | 
			
		||||
  void onSelectiveDownloadingCompletes();
 | 
			
		||||
public:
 | 
			
		||||
  TorrentConsoleDownloadEngine();
 | 
			
		||||
  ~TorrentConsoleDownloadEngine();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,7 +22,7 @@
 | 
			
		|||
#include "TorrentDownloadEngine.h"
 | 
			
		||||
 | 
			
		||||
void TorrentDownloadEngine::onEndOfRun() {
 | 
			
		||||
  torrentMan->diskWriter->closeFile();
 | 
			
		||||
  torrentMan->diskAdaptor->closeFile();
 | 
			
		||||
  if(filenameFixed && torrentMan->downloadComplete()) {
 | 
			
		||||
    torrentMan->remove();
 | 
			
		||||
  } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -32,8 +32,8 @@ void TorrentDownloadEngine::onEndOfRun() {
 | 
			
		|||
 | 
			
		||||
void TorrentDownloadEngine::afterEachIteration() {
 | 
			
		||||
  if(!filenameFixed && torrentMan->downloadComplete()) {
 | 
			
		||||
    if(torrentMan->isPartialDownloadingMode()) {
 | 
			
		||||
      onPartialDownloadingCompletes();
 | 
			
		||||
    if(torrentMan->isSelectiveDownloadingMode()) {
 | 
			
		||||
      onSelectiveDownloadingCompletes();
 | 
			
		||||
    }
 | 
			
		||||
    torrentMan->onDownloadComplete();
 | 
			
		||||
    if(torrentMan->downloadComplete()) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,7 +31,7 @@ private:
 | 
			
		|||
protected:
 | 
			
		||||
  void onEndOfRun();
 | 
			
		||||
  void afterEachIteration();
 | 
			
		||||
  virtual void onPartialDownloadingCompletes() = 0;
 | 
			
		||||
  virtual void onSelectiveDownloadingCompletes() = 0;
 | 
			
		||||
public:
 | 
			
		||||
  TorrentDownloadEngine():filenameFixed(false) {}
 | 
			
		||||
  virtual ~TorrentDownloadEngine() {}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,6 +32,9 @@
 | 
			
		|||
#include "DefaultDiskWriter.h"
 | 
			
		||||
#include "MultiDiskWriter.h"
 | 
			
		||||
#include "prefs.h"
 | 
			
		||||
#include "CopyDiskAdaptor.h"
 | 
			
		||||
#include "DirectDiskAdaptor.h"
 | 
			
		||||
#include "MultiDiskAdaptor.h"
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <libgen.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -42,25 +45,21 @@ TorrentMan::TorrentMan():bitfield(NULL),
 | 
			
		|||
			 preDownloadLength(0), preUploadLength(0),
 | 
			
		||||
			 deltaDownloadLength(0), deltaUploadLength(0),
 | 
			
		||||
			 storeDir("."),
 | 
			
		||||
			 multiFileTopDir(NULL),
 | 
			
		||||
			 setupComplete(false),
 | 
			
		||||
			 interval(DEFAULT_ANNOUNCE_INTERVAL),
 | 
			
		||||
			 minInterval(DEFAULT_ANNOUNCE_MIN_INTERVAL),
 | 
			
		||||
			 complete(0), incomplete(0),
 | 
			
		||||
			 connections(0), diskWriter(NULL) {}
 | 
			
		||||
			 connections(0), diskAdaptor(NULL) {}
 | 
			
		||||
 | 
			
		||||
TorrentMan::~TorrentMan() {
 | 
			
		||||
  if(bitfield != NULL) {
 | 
			
		||||
    delete bitfield;
 | 
			
		||||
  }
 | 
			
		||||
  if(multiFileTopDir != NULL) {
 | 
			
		||||
    delete multiFileTopDir;
 | 
			
		||||
  }
 | 
			
		||||
  for(Peers::iterator itr = peers.begin(); itr != peers.end(); itr++) {
 | 
			
		||||
    delete *itr;
 | 
			
		||||
  }
 | 
			
		||||
  if(diskWriter != NULL) {
 | 
			
		||||
    delete diskWriter;
 | 
			
		||||
  if(diskAdaptor != NULL) {
 | 
			
		||||
    delete diskAdaptor;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -298,7 +297,7 @@ bool TorrentMan::downloadComplete() const {
 | 
			
		|||
  return bitfield->isAllBitSet();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TorrentMan::readFileEntry(const Dictionary* infoDic, const string& defaultName) {
 | 
			
		||||
void TorrentMan::readFileEntry(FileEntries& fileEntries, Directory** pTopDir, const Dictionary* infoDic, const string& defaultName) {
 | 
			
		||||
  Data* topName = (Data*)infoDic->get("name");
 | 
			
		||||
  if(topName != NULL) {
 | 
			
		||||
    name = topName->toString();
 | 
			
		||||
| 
						 | 
				
			
			@ -313,12 +312,14 @@ void TorrentMan::readFileEntry(const Dictionary* infoDic, const string& defaultN
 | 
			
		|||
    setFileMode(SINGLE);
 | 
			
		||||
    Data* length = (Data*)infoDic->get("length");
 | 
			
		||||
    totalLength = length->toLLInt();
 | 
			
		||||
    FileEntry fileEntry(name, totalLength, 0);
 | 
			
		||||
    fileEntries.push_back(fileEntry);
 | 
			
		||||
  } else {
 | 
			
		||||
    long long int length = 0;
 | 
			
		||||
    long long int offset = 0;
 | 
			
		||||
    // multi-file mode
 | 
			
		||||
    setFileMode(MULTI);
 | 
			
		||||
    multiFileTopDir = new Directory(name);
 | 
			
		||||
    *pTopDir = new Directory(name);
 | 
			
		||||
    const MetaList& metaList = files->getList();
 | 
			
		||||
    for(MetaList::const_iterator itr = metaList.begin(); itr != metaList.end();
 | 
			
		||||
	itr++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -327,7 +328,7 @@ void TorrentMan::readFileEntry(const Dictionary* infoDic, const string& defaultN
 | 
			
		|||
      length += lengthData->toLLInt();
 | 
			
		||||
      List* path = (List*)fileDic->get("path");
 | 
			
		||||
      const MetaList& paths = path->getList();
 | 
			
		||||
      Directory* parentDir = multiFileTopDir;
 | 
			
		||||
      Directory* parentDir = *pTopDir;
 | 
			
		||||
      string filePath = name;
 | 
			
		||||
      for(int i = 0; i < (int)paths.size()-1; i++) {
 | 
			
		||||
	Data* subpath = (Data*)paths.at(i);
 | 
			
		||||
| 
						 | 
				
			
			@ -339,14 +340,14 @@ void TorrentMan::readFileEntry(const Dictionary* infoDic, const string& defaultN
 | 
			
		|||
      Data* lastpath = (Data*)paths.back();
 | 
			
		||||
      filePath.append("/").append(lastpath->toString());
 | 
			
		||||
      FileEntry fileEntry(filePath, lengthData->toLLInt(), offset);
 | 
			
		||||
      multiFileEntries.push_back(fileEntry);
 | 
			
		||||
      fileEntries.push_back(fileEntry);
 | 
			
		||||
      offset += fileEntry.length;
 | 
			
		||||
    }
 | 
			
		||||
    totalLength = length;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TorrentMan::setup(string metaInfoFile) {
 | 
			
		||||
void TorrentMan::setup(string metaInfoFile, const Strings& targetFilePaths) {
 | 
			
		||||
  peerId = "-A2****-";
 | 
			
		||||
  for(int i = 0; i < 12; i++) {
 | 
			
		||||
    peerId += Util::itos((int)(((double)10)*random()/(RAND_MAX+1.0)));
 | 
			
		||||
| 
						 | 
				
			
			@ -363,7 +364,9 @@ void TorrentMan::setup(string metaInfoFile) {
 | 
			
		|||
  v.getHash(md, len);
 | 
			
		||||
  setInfoHash(md);
 | 
			
		||||
 | 
			
		||||
  readFileEntry(infoDic, metaInfoFile);
 | 
			
		||||
  FileEntries fileEntries;
 | 
			
		||||
  Directory* topDir = NULL;
 | 
			
		||||
  readFileEntry(fileEntries, &topDir, infoDic, metaInfoFile);
 | 
			
		||||
 | 
			
		||||
  announce = ((Data*)topDic->get("announce"))->toString();
 | 
			
		||||
  pieceLength = ((Data*)infoDic->get("piece length"))->toInt();
 | 
			
		||||
| 
						 | 
				
			
			@ -380,45 +383,54 @@ void TorrentMan::setup(string metaInfoFile) {
 | 
			
		|||
 | 
			
		||||
  initBitfield();
 | 
			
		||||
  delete topDic;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TorrentMan::setupDiskWriter() {
 | 
			
		||||
  if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE) {
 | 
			
		||||
    if(segmentFileExists()) {
 | 
			
		||||
      load();
 | 
			
		||||
    }
 | 
			
		||||
    if(fileMode == SINGLE) {
 | 
			
		||||
      diskWriter = new DefaultDiskWriter();
 | 
			
		||||
      diskAdaptor = new DirectDiskAdaptor(new DefaultDiskWriter(totalLength));
 | 
			
		||||
    } else {
 | 
			
		||||
      diskWriter = new MultiDiskWriter();
 | 
			
		||||
      ((MultiDiskWriter*)diskWriter)->setMultiFileEntries(multiFileEntries, pieceLength);
 | 
			
		||||
      multiFileTopDir->createDir(storeDir, true);
 | 
			
		||||
      diskAdaptor = new MultiDiskAdaptor(new MultiDiskWriter(pieceLength));
 | 
			
		||||
    }
 | 
			
		||||
    diskWriter->openFile(getFilePath());
 | 
			
		||||
  } else {
 | 
			
		||||
    if(option->get(PREF_NO_PREALLOCATION) == V_TRUE) {
 | 
			
		||||
      diskWriter = new DefaultDiskWriter();
 | 
			
		||||
    } else {
 | 
			
		||||
      diskWriter = new PreAllocationDiskWriter(totalLength);
 | 
			
		||||
    }
 | 
			
		||||
    if(segmentFileExists()) {
 | 
			
		||||
      load();
 | 
			
		||||
      diskWriter->openExistingFile(getTempFilePath());
 | 
			
		||||
    } else {
 | 
			
		||||
      diskWriter->initAndOpenFile(getTempFilePath());
 | 
			
		||||
    }
 | 
			
		||||
    diskAdaptor = new CopyDiskAdaptor(new DefaultDiskWriter(totalLength));
 | 
			
		||||
    ((CopyDiskAdaptor*)diskAdaptor)->setTempFilename(name+".a2tmp");
 | 
			
		||||
  }
 | 
			
		||||
  diskAdaptor->setStoreDir(storeDir);
 | 
			
		||||
  diskAdaptor->setTopDir(topDir);
 | 
			
		||||
  diskAdaptor->setFileEntries(fileEntries);
 | 
			
		||||
  setFileFilter(targetFilePaths);
 | 
			
		||||
  if(segmentFileExists()) {
 | 
			
		||||
    load();
 | 
			
		||||
    diskAdaptor->openExistingFile();
 | 
			
		||||
  } else {
 | 
			
		||||
    diskAdaptor->initAndOpenFile();
 | 
			
		||||
  }
 | 
			
		||||
  setupComplete = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const MultiFileEntries& TorrentMan::getMultiFileEntries() const {
 | 
			
		||||
  return multiFileEntries;
 | 
			
		||||
void TorrentMan::setFileFilter(const Strings& filePaths) {
 | 
			
		||||
  if(fileMode != MULTI || filePaths.empty()) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  diskAdaptor->removeAllDownloadEntry();
 | 
			
		||||
  for(Strings::const_iterator pitr = filePaths.begin();
 | 
			
		||||
      pitr != filePaths.end(); pitr++) {
 | 
			
		||||
    if(!diskAdaptor->addDownloadEntry(*pitr)) {
 | 
			
		||||
      throw new DlAbortEx("no such file entry <%s>", (*pitr).c_str());
 | 
			
		||||
    }
 | 
			
		||||
    FileEntry fileEntry = diskAdaptor->getFileEntryFromPath(*pitr);
 | 
			
		||||
    bitfield->addFilter(fileEntry.offset, fileEntry.length);
 | 
			
		||||
  }
 | 
			
		||||
  bitfield->enableFilter();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TorrentMan::readFileEntryFromMetaInfoFile(const string& metaInfoFile) {
 | 
			
		||||
FileEntries TorrentMan::readFileEntryFromMetaInfoFile(const string& metaInfoFile) {
 | 
			
		||||
  Dictionary* topDic = (Dictionary*)MetaFileUtil::parseMetaFile(metaInfoFile);
 | 
			
		||||
  const Dictionary* infoDic = (const Dictionary*)topDic->get("info");
 | 
			
		||||
  readFileEntry(infoDic, metaInfoFile);
 | 
			
		||||
  FileEntries fileEntries;
 | 
			
		||||
  Directory* topDir;
 | 
			
		||||
  readFileEntry(fileEntries, &topDir, infoDic, metaInfoFile);
 | 
			
		||||
  delete topDir;
 | 
			
		||||
  return fileEntries;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
string TorrentMan::getName() const {
 | 
			
		||||
| 
						 | 
				
			
			@ -433,28 +445,8 @@ string TorrentMan::getPieceHash(int index) const {
 | 
			
		|||
  return pieceHashes.at(index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
string TorrentMan::getFilePath() const {
 | 
			
		||||
  if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE && fileMode == MULTI) {
 | 
			
		||||
    return storeDir;
 | 
			
		||||
  } else {
 | 
			
		||||
    return storeDir+"/"+name;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
string TorrentMan::getTempFilePath() const {
 | 
			
		||||
  if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE) {
 | 
			
		||||
    return getFilePath();
 | 
			
		||||
  } else {
 | 
			
		||||
    return getFilePath()+".a2tmp";
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
string TorrentMan::getSegmentFilePath() const {
 | 
			
		||||
  if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE && fileMode == MULTI) {
 | 
			
		||||
    return storeDir+"/"+name+".aria2";
 | 
			
		||||
  } else {
 | 
			
		||||
    return getFilePath()+".aria2";
 | 
			
		||||
  }
 | 
			
		||||
  return storeDir+"/"+name+".aria2";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool TorrentMan::segmentFileExists() const {
 | 
			
		||||
| 
						 | 
				
			
			@ -546,117 +538,27 @@ void TorrentMan::remove() const {
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TorrentMan::fixFilename() {
 | 
			
		||||
  if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE) {
 | 
			
		||||
    // nothing to do here
 | 
			
		||||
  } else {
 | 
			
		||||
    if(fileMode == SINGLE) {
 | 
			
		||||
      copySingleFile();
 | 
			
		||||
    } else {
 | 
			
		||||
      splitMultiFile();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TorrentMan::copySingleFile() const {
 | 
			
		||||
  logger->info("writing file %s", getFilePath().c_str());
 | 
			
		||||
  Util::fileCopy(getFilePath(), getTempFilePath());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TorrentMan::splitMultiFile() {
 | 
			
		||||
  logger->info("creating directories");
 | 
			
		||||
  multiFileTopDir->createDir(storeDir, true);
 | 
			
		||||
  long long int offset = 0;
 | 
			
		||||
  for(MultiFileEntries::iterator itr = multiFileEntries.begin();
 | 
			
		||||
      itr != multiFileEntries.end(); itr++) {
 | 
			
		||||
    if(!itr->extracted && itr->requested) {
 | 
			
		||||
      string dest = storeDir+"/"+itr->path;
 | 
			
		||||
      logger->info("writing file %s", dest.c_str());
 | 
			
		||||
      Util::rangedFileCopy(dest, getTempFilePath(), offset, itr->length);
 | 
			
		||||
      itr->extracted = true;
 | 
			
		||||
    }
 | 
			
		||||
    offset += itr->length;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TorrentMan::deleteTempFile() const {
 | 
			
		||||
  if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE) {
 | 
			
		||||
    // nothing to do here
 | 
			
		||||
  } else {
 | 
			
		||||
    unlink(getTempFilePath().c_str());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// bool TorrentMan::unextractedFileEntryExists() const {
 | 
			
		||||
//   if(fileMode == SINGLE) {
 | 
			
		||||
//     return false;
 | 
			
		||||
//   }
 | 
			
		||||
//   for(MultiFileEntries::const_iterator itr = multiFileEntries.begin();
 | 
			
		||||
//       itr != multiFileEntries.end(); itr++) {
 | 
			
		||||
//     if(!itr->extracted) {
 | 
			
		||||
//       return true;
 | 
			
		||||
//     }
 | 
			
		||||
//   }
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
void TorrentMan::setFileEntriesToDownload(const Strings& filePaths) {
 | 
			
		||||
  if(fileMode != MULTI) {
 | 
			
		||||
    throw new DlAbortEx("only multi-mode supports partial downloading mode.");
 | 
			
		||||
  }
 | 
			
		||||
  // clear all requested flags in multiFileEntries.
 | 
			
		||||
  setAllMultiFileRequestedState(false);
 | 
			
		||||
  for(Strings::const_iterator pitr = filePaths.begin();
 | 
			
		||||
      pitr != filePaths.end(); pitr++) {
 | 
			
		||||
    bool found = false;
 | 
			
		||||
    for(MultiFileEntries::iterator itr = multiFileEntries.begin();
 | 
			
		||||
	itr != multiFileEntries.end(); itr++) {
 | 
			
		||||
      if(*pitr == itr->path) {
 | 
			
		||||
	itr->requested = true;
 | 
			
		||||
	found = true;
 | 
			
		||||
	bitfield->addFilter(itr->offset, itr->length);
 | 
			
		||||
	break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if(!found) {
 | 
			
		||||
      throw new DlAbortEx("no such file entry <%s>", (*pitr).c_str());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  bitfield->enableFilter();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool TorrentMan::isPartialDownloadingMode() const {
 | 
			
		||||
bool TorrentMan::isSelectiveDownloadingMode() const {
 | 
			
		||||
  return bitfield->isFilterEnabled();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TorrentMan::setAllMultiFileRequestedState(bool state) {
 | 
			
		||||
  for(MultiFileEntries::iterator itr = multiFileEntries.begin();
 | 
			
		||||
      itr != multiFileEntries.end(); itr++) {
 | 
			
		||||
    itr->requested = state;
 | 
			
		||||
  }  
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TorrentMan::finishPartialDownloadingMode() {
 | 
			
		||||
void TorrentMan::finishSelectiveDownloadingMode() {
 | 
			
		||||
  bitfield->clearFilter();
 | 
			
		||||
  setAllMultiFileRequestedState(true);
 | 
			
		||||
  if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE && fileMode == MULTI) {
 | 
			
		||||
    ((MultiDiskWriter*)diskWriter)->setMultiFileEntries(multiFileEntries, pieceLength);
 | 
			
		||||
  }
 | 
			
		||||
  diskAdaptor->addAllDownloadEntry();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
long long int TorrentMan::getCompletedLength() const {
 | 
			
		||||
  return bitfield->getCompletedLength();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
long long int TorrentMan::getPartialTotalLength() const {
 | 
			
		||||
long long int TorrentMan::getSelectedTotalLength() const {
 | 
			
		||||
  return bitfield->getFilteredTotalLength();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TorrentMan::onDownloadComplete() {
 | 
			
		||||
  diskWriter->closeFile();
 | 
			
		||||
  save();
 | 
			
		||||
  fixFilename();
 | 
			
		||||
  if(isPartialDownloadingMode()) {
 | 
			
		||||
    finishPartialDownloadingMode();
 | 
			
		||||
  diskAdaptor->onDownloadComplete();
 | 
			
		||||
  if(isSelectiveDownloadingMode()) {
 | 
			
		||||
    finishSelectiveDownloadingMode();
 | 
			
		||||
  }
 | 
			
		||||
  diskWriter->openFile(getTempFilePath());
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,9 +28,10 @@
 | 
			
		|||
#include "BitfieldMan.h"
 | 
			
		||||
#include "DiskWriter.h"
 | 
			
		||||
#include "Piece.h"
 | 
			
		||||
#include "Directory.h"
 | 
			
		||||
#include "Dictionary.h"
 | 
			
		||||
#include "Option.h"
 | 
			
		||||
#include "FileEntry.h"
 | 
			
		||||
#include "DiskAdaptor.h"
 | 
			
		||||
#include <deque>
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <string>
 | 
			
		||||
| 
						 | 
				
			
			@ -46,22 +47,8 @@ using namespace std;
 | 
			
		|||
#define END_GAME_PIECE_NUM 20
 | 
			
		||||
#define MAX_PEER_ERROR 5
 | 
			
		||||
 | 
			
		||||
class FileEntry {
 | 
			
		||||
public:
 | 
			
		||||
  string path;
 | 
			
		||||
  long long int length;
 | 
			
		||||
  long long int offset;
 | 
			
		||||
  bool extracted;
 | 
			
		||||
  bool requested;
 | 
			
		||||
  FileEntry(string path, long long int length, long long int offset):
 | 
			
		||||
    path(path), length(length), offset(offset),
 | 
			
		||||
    extracted(false), requested(true) {}
 | 
			
		||||
  ~FileEntry() {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef deque<Peer*> Peers;
 | 
			
		||||
typedef multimap<int, int> Haves;
 | 
			
		||||
typedef deque<FileEntry> MultiFileEntries;
 | 
			
		||||
typedef deque<Piece> UsedPieces;
 | 
			
		||||
typedef deque<int> PieceIndexes;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -85,8 +72,6 @@ private:
 | 
			
		|||
  int port;
 | 
			
		||||
  Haves haves;
 | 
			
		||||
  UsedPieces usedPieces;
 | 
			
		||||
  Directory* multiFileTopDir;
 | 
			
		||||
  MultiFileEntries multiFileEntries;
 | 
			
		||||
  bool setupComplete;
 | 
			
		||||
 | 
			
		||||
  FILE* openSegFile(string segFilename, string mode) const;
 | 
			
		||||
| 
						 | 
				
			
			@ -97,7 +82,8 @@ private:
 | 
			
		|||
  void deleteUsedPiece(const Piece& piece);
 | 
			
		||||
  int deleteUsedPiecesByFillRate(int fillRate, int toDelete);
 | 
			
		||||
  void reduceUsedPieces(int max);
 | 
			
		||||
  void readFileEntry(const Dictionary* infoDic, const string& defaultName);
 | 
			
		||||
  void readFileEntry(FileEntries& fileEntries, Directory** pTopDir, const Dictionary* infoDic, const string& defaultName);
 | 
			
		||||
  void setFileFilter(const Strings& filePaths);
 | 
			
		||||
public:
 | 
			
		||||
  int pieceLength;
 | 
			
		||||
  int pieces;
 | 
			
		||||
| 
						 | 
				
			
			@ -115,7 +101,7 @@ public:
 | 
			
		|||
  ~TorrentMan();
 | 
			
		||||
 | 
			
		||||
  const Logger* logger;
 | 
			
		||||
  DiskWriter* diskWriter;
 | 
			
		||||
  DiskAdaptor* diskAdaptor;
 | 
			
		||||
  const Option* option;
 | 
			
		||||
 | 
			
		||||
  int getNewCuid() { return ++cuidCounter; }
 | 
			
		||||
| 
						 | 
				
			
			@ -150,8 +136,7 @@ public:
 | 
			
		|||
    return infoHash;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void setup(string metaInfoFile);
 | 
			
		||||
  void setupDiskWriter();
 | 
			
		||||
  void setup(string metaInfoFile, const Strings& targetFilePaths);
 | 
			
		||||
 | 
			
		||||
  string getPieceHash(int index) const;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -213,8 +198,6 @@ public:
 | 
			
		|||
  string getStoreDir() const { return storeDir; }
 | 
			
		||||
  void setStoreDir(string dir) { storeDir = dir; }
 | 
			
		||||
 | 
			
		||||
  string getFilePath() const;
 | 
			
		||||
  string getTempFilePath() const;
 | 
			
		||||
  string getSegmentFilePath() const;
 | 
			
		||||
 | 
			
		||||
  bool segmentFileExists() const;  
 | 
			
		||||
| 
						 | 
				
			
			@ -233,20 +216,14 @@ public:
 | 
			
		|||
  int countUsedPiece() const { return usedPieces.size(); }
 | 
			
		||||
  int countAdvertisedPiece() const { return haves.size(); }
 | 
			
		||||
 | 
			
		||||
  void readFileEntryFromMetaInfoFile(const string& metaInfoFile);
 | 
			
		||||
  const MultiFileEntries& getMultiFileEntries() const;
 | 
			
		||||
  FileEntries readFileEntryFromMetaInfoFile(const string& metaInfoFile);
 | 
			
		||||
  string getName() const;
 | 
			
		||||
 | 
			
		||||
  //bool unextractedFileEntryExists() const;
 | 
			
		||||
  
 | 
			
		||||
  void setAllMultiFileRequestedState(bool state);
 | 
			
		||||
  void finishPartialDownloadingMode();
 | 
			
		||||
  bool isPartialDownloadingMode() const;
 | 
			
		||||
 | 
			
		||||
  void setFileEntriesToDownload(const Strings& filePaths);
 | 
			
		||||
  void finishSelectiveDownloadingMode();
 | 
			
		||||
  bool isSelectiveDownloadingMode() const;
 | 
			
		||||
 | 
			
		||||
  long long int getCompletedLength() const;
 | 
			
		||||
  long long int getPartialTotalLength() const;
 | 
			
		||||
  long long int getSelectedTotalLength() const;
 | 
			
		||||
 | 
			
		||||
  void onDownloadComplete();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										49
									
								
								src/main.cc
								
								
								
								
							
							
						
						
									
										49
									
								
								src/main.cc
								
								
								
								
							| 
						 | 
				
			
			@ -63,6 +63,10 @@ void printDownloadCompeleteMessage(string filename) {
 | 
			
		|||
  printf(_("\nThe download was complete. <%s>\n"), filename.c_str());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void printDownloadCompeleteMessage() {
 | 
			
		||||
  printf("\nThe download was complete.\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void printDownloadAbortMessage() {
 | 
			
		||||
  printf(_("\nThe download was not complete because of errors. Check the log.\n"));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -85,13 +89,13 @@ void handler(int signal) {
 | 
			
		|||
 | 
			
		||||
void torrentHandler(int signal) {
 | 
			
		||||
  cout << _("\nSIGINT signal received.") << endl;
 | 
			
		||||
  if(te->torrentMan->diskWriter != NULL) {
 | 
			
		||||
    te->torrentMan->diskWriter->closeFile();
 | 
			
		||||
  if(te->torrentMan->diskAdaptor != NULL) {
 | 
			
		||||
    te->torrentMan->diskAdaptor->closeFile();
 | 
			
		||||
  }
 | 
			
		||||
  if(te->torrentMan->downloadComplete() && te->isFilenameFixed()) {
 | 
			
		||||
    te->torrentMan->remove();
 | 
			
		||||
    te->torrentMan->deleteTempFile();
 | 
			
		||||
    printDownloadCompeleteMessage(te->torrentMan->getFilePath());
 | 
			
		||||
    //te->torrentMan->deleteTempFile();
 | 
			
		||||
    printDownloadCompeleteMessage();
 | 
			
		||||
  } else {
 | 
			
		||||
    te->torrentMan->save();
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -283,7 +287,7 @@ int main(int argc, char* argv[]) {
 | 
			
		|||
#ifdef ENABLE_BITTORRENT
 | 
			
		||||
      { "torrent-file", required_argument, &lopt, 15 },
 | 
			
		||||
      { "follow-torrent", required_argument, &lopt, 16 },
 | 
			
		||||
      { "torrent-show-files", no_argument, &lopt, 17 },
 | 
			
		||||
      { "show-files", no_argument, &lopt, 17 },
 | 
			
		||||
      { "no-preallocation", no_argument, &lopt, 18 },
 | 
			
		||||
      { "direct-file-mapping", required_argument, &lopt, 19 },
 | 
			
		||||
#endif // ENABLE_BITTORRENT
 | 
			
		||||
| 
						 | 
				
			
			@ -414,7 +418,7 @@ int main(int argc, char* argv[]) {
 | 
			
		|||
	}
 | 
			
		||||
	break;
 | 
			
		||||
      case 17:
 | 
			
		||||
	op->put(PREF_TORRENT_SHOW_FILES, V_TRUE);
 | 
			
		||||
	op->put(PREF_SHOW_FILES, V_TRUE);
 | 
			
		||||
	break;
 | 
			
		||||
      case 18:
 | 
			
		||||
	op->put(PREF_NO_PREALLOCATION, V_TRUE);
 | 
			
		||||
| 
						 | 
				
			
			@ -608,32 +612,21 @@ int main(int argc, char* argv[]) {
 | 
			
		|||
      te->torrentMan->option = op;
 | 
			
		||||
      string targetTorrentFile = torrentFile.empty() ?
 | 
			
		||||
	downloadedTorrentFile : torrentFile;
 | 
			
		||||
      if(op->get(PREF_TORRENT_SHOW_FILES) == V_TRUE) {
 | 
			
		||||
	te->torrentMan->readFileEntryFromMetaInfoFile(targetTorrentFile);
 | 
			
		||||
      if(op->get(PREF_SHOW_FILES) == V_TRUE) {
 | 
			
		||||
	FileEntries fileEntries = te->torrentMan->readFileEntryFromMetaInfoFile(targetTorrentFile);
 | 
			
		||||
	cout << "Files:" << endl;
 | 
			
		||||
	switch(te->torrentMan->getFileMode()) {
 | 
			
		||||
	case TorrentMan::SINGLE:
 | 
			
		||||
	  printf("%s %s Bytes\n", te->torrentMan->getName().c_str(),
 | 
			
		||||
		 Util::llitos(te->torrentMan->getTotalLength(), true).c_str());
 | 
			
		||||
	  break;
 | 
			
		||||
	case TorrentMan::MULTI: {
 | 
			
		||||
	  const MultiFileEntries& entries = te->torrentMan->getMultiFileEntries();
 | 
			
		||||
	  for(MultiFileEntries::const_iterator itr = entries.begin();
 | 
			
		||||
	      itr != entries.end(); itr++) {
 | 
			
		||||
	    printf("%s %s Bytes\n", itr->path.c_str(),
 | 
			
		||||
		   Util::llitos(itr->length, true).c_str());
 | 
			
		||||
	  }
 | 
			
		||||
	  break;
 | 
			
		||||
	}
 | 
			
		||||
	for(FileEntries::const_iterator itr = fileEntries.begin();
 | 
			
		||||
	    itr != fileEntries.end(); itr++) {
 | 
			
		||||
	  printf("%s %s Bytes\n", itr->path.c_str(),
 | 
			
		||||
		 Util::llitos(itr->length, true).c_str());
 | 
			
		||||
	}
 | 
			
		||||
	exit(0);
 | 
			
		||||
      } else {
 | 
			
		||||
	te->torrentMan->setup(targetTorrentFile);
 | 
			
		||||
	if(!torrentFile.empty() && !args.empty() &&
 | 
			
		||||
	   te->torrentMan->getFileMode() == TorrentMan::MULTI) {
 | 
			
		||||
	  te->torrentMan->setFileEntriesToDownload(args);
 | 
			
		||||
	Strings targetFiles;
 | 
			
		||||
	if(!torrentFile.empty() && !args.empty()) {
 | 
			
		||||
	  targetFiles = args;
 | 
			
		||||
	}
 | 
			
		||||
	te->torrentMan->setupDiskWriter();
 | 
			
		||||
	te->torrentMan->setup(targetTorrentFile, targetFiles);
 | 
			
		||||
      }
 | 
			
		||||
      PeerListenCommand* listenCommand =
 | 
			
		||||
	new PeerListenCommand(te->torrentMan->getNewCuid(), te);
 | 
			
		||||
| 
						 | 
				
			
			@ -652,7 +645,7 @@ int main(int argc, char* argv[]) {
 | 
			
		|||
      te->run();
 | 
			
		||||
      
 | 
			
		||||
      if(te->torrentMan->downloadComplete()) {
 | 
			
		||||
	printDownloadCompeleteMessage(te->torrentMan->getFilePath());
 | 
			
		||||
	printDownloadCompeleteMessage();
 | 
			
		||||
      } else {
 | 
			
		||||
	printDownloadAbortMessage();
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -89,7 +89,7 @@
 | 
			
		|||
// values: 1*digit
 | 
			
		||||
#define PREF_PEER_CONNECTION_TIMEOUT "peer_connection_timeout"
 | 
			
		||||
// values: true | false
 | 
			
		||||
#define PREF_TORRENT_SHOW_FILES "torrent_show_files"
 | 
			
		||||
#define PREF_SHOW_FILES "show_files"
 | 
			
		||||
// values: true | false
 | 
			
		||||
#define PREF_NO_PREALLOCATION "no_preallocation"
 | 
			
		||||
// values: true | false
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,14 +25,14 @@ public:
 | 
			
		|||
 | 
			
		||||
CPPUNIT_TEST_SUITE_REGISTRATION( MultiDiskWriterTest );
 | 
			
		||||
 | 
			
		||||
MultiFileEntries createEntries() {
 | 
			
		||||
FileEntries createEntries() {
 | 
			
		||||
  FileEntry entry1("file1.txt", 15, 0);
 | 
			
		||||
  FileEntry entry2("file2.txt", 7, 15);
 | 
			
		||||
  FileEntry entry3("file3.txt", 3, 22);
 | 
			
		||||
  unlink("file1.txt");
 | 
			
		||||
  unlink("file2.txt");
 | 
			
		||||
  unlink("file3.txt");
 | 
			
		||||
  MultiFileEntries entries;
 | 
			
		||||
  FileEntries entries;
 | 
			
		||||
  entries.push_back(entry1);
 | 
			
		||||
  entries.push_back(entry2);
 | 
			
		||||
  entries.push_back(entry3);
 | 
			
		||||
| 
						 | 
				
			
			@ -52,8 +52,8 @@ void readFile(const string& filename, char* buf, int bufLength) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void MultiDiskWriterTest::testWriteData() {
 | 
			
		||||
  MultiDiskWriter dw;
 | 
			
		||||
  dw.setMultiFileEntries(createEntries(), 2);
 | 
			
		||||
  MultiDiskWriter dw(2);
 | 
			
		||||
  dw.setFileEntries(createEntries());
 | 
			
		||||
 | 
			
		||||
  dw.openFile(".");
 | 
			
		||||
  string msg = "12345";
 | 
			
		||||
| 
						 | 
				
			
			@ -97,12 +97,12 @@ void MultiDiskWriterTest::testReadData() {
 | 
			
		|||
  FileEntry entry1("file1r.txt", 15, 0);
 | 
			
		||||
  FileEntry entry2("file2r.txt", 7, 15);
 | 
			
		||||
  FileEntry entry3("file3r.txt", 3, 22);
 | 
			
		||||
  MultiFileEntries entries;
 | 
			
		||||
  FileEntries entries;
 | 
			
		||||
  entries.push_back(entry1);
 | 
			
		||||
  entries.push_back(entry2);
 | 
			
		||||
  entries.push_back(entry3);
 | 
			
		||||
  MultiDiskWriter dw;
 | 
			
		||||
  dw.setMultiFileEntries(entries, 2);
 | 
			
		||||
  MultiDiskWriter dw(2);
 | 
			
		||||
  dw.setFileEntries(entries);
 | 
			
		||||
 | 
			
		||||
  dw.openFile(".");
 | 
			
		||||
  char buf[128];
 | 
			
		||||
| 
						 | 
				
			
			@ -124,12 +124,12 @@ void MultiDiskWriterTest::testSha1Sum() {
 | 
			
		|||
  FileEntry entry1("file1r.txt", 15, 0);
 | 
			
		||||
  FileEntry entry2("file2r.txt", 7, 15);
 | 
			
		||||
  FileEntry entry3("file3r.txt", 3, 22);
 | 
			
		||||
  MultiFileEntries entries;
 | 
			
		||||
  FileEntries entries;
 | 
			
		||||
  entries.push_back(entry1);
 | 
			
		||||
  entries.push_back(entry2);
 | 
			
		||||
  entries.push_back(entry3);
 | 
			
		||||
  MultiDiskWriter dw;
 | 
			
		||||
  dw.setMultiFileEntries(entries, 2);
 | 
			
		||||
  MultiDiskWriter dw(2);
 | 
			
		||||
  dw.setFileEntries(entries);
 | 
			
		||||
 | 
			
		||||
  dw.openFile(".");
 | 
			
		||||
  string sha1sum = dw.sha1Sum(0, 25);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue