diff options
| author | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2006-11-05 15:04:17 +0000 |
|---|---|---|
| committer | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2006-11-05 15:04:17 +0000 |
| commit | ec642ad294dd8fe6238b3a47309293c1c77beb68 (patch) | |
| tree | 148f3116687d3f1cc413810fa067ca52d56aa68e /src | |
| parent | b8737b0e7c92fb4a5b1c8b6173663381aacca40c (diff) | |
2006-11-05 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
To divide TorrentMan into 6 classes: BtContext, BtRuntime,
PeerStorage, PieceStorage, BtAnnounce and BtProgressInfoFile
* src/TrackerWatcherComand.h: Made subclass of
BtContextAwareCommand.
* src/SeedCheckCommand.cc: Use pieceStorage, btRuntime
* src/PeerAbstractCommand.h: Made subclass of
BtContextAwareCommand.
* src/PeerAbstractCommand.cc: Use btRuntime.
* src/BtContextAwareCommand.h: New class.
* src/FileEntry.h: Added accessor methods for following
variables.
(path): Made private.
(length): Made private.
(offset): Made private.
(extracted): Made private.
(requested): Made private.
(FileEntries): New definition.
(FileEntryHandle): New definition.
* src/FileEntry.cc: New file.
* src/HaveEraseCommand.h: Made subclass of
BtContextAwareCommand.
* src/HaveEraseCommand.cc: Use btRuntime, pieceStorage.
* src/PeerChokeCommand.h: Made subclass of
BtContextAwareCommand.
* src/PeerChokeCommand.cc: Use btRuntime, peerStorage,
pieceStorage.
* src/PieceStorage.h: New file.
* src/PeerInteractionCommand.h: Use btContext.
* src/PeerInteractionCommand.cc: Use pieceStorage, peerStorage,
btRuntime.
* src/DefaultBtProgressInfoFile.h: New file.
* src/DefaultBtProgressInfoFile.cc: New file.
* src/File.cc
(Util.h): New include.
(mkdirs): New function.
* src/MultiDiskAdaptor.h
(mkdir): New function.
* src/PeerListProcessor.h
(Peers): Removed.
* src/PeerInteraction.h
(torrentMan): Removed.
(btContext): New variable.
(peerStorage): New variable.
(pieceStorage): New variable.
(btAnnounce): New variable.
(getTorrentMan): Removed.
(getBtContext): New function.
* src/PeerInteraction.cc: Use btContext, peerStorage,
pieceStorage,
btAnnounce.
* src/HandshakeMessage.h
(TorrentMan.h): Removed.
* src/HandshakeMessage.cc: Use btContext.
* src/DefaultBtAnnounce.cc: New file.
* src/MultiDiskWriter.cc: Use the accessor methods of FileEntry.
* src/DefaultPieceStorage.cc: New file.
* src/DefaultBtContext.h: New file.
* src/TorrentRequestInfo.cc: Use btContext, pieceStorage.
Use the accessor methods of FileEntry.
* src/CookieBox.cc: Updated to use Util::slice().
* src/PieceMessage.cc: Use btContext, pieceStorage.
* src/common.h (SharedHandle.h): New include.
* src/PeerMessage.cc (PeerMessage): Added btContext,
peerStorage,
pieceStorage.
* src/TorrentAutoSaveCommand.h: Made subclass of
BtContextAwareCommand.
* src/DiskAdaptor.h
(topDir): Removed.
(getFileEntryFromPath): Changed the return type to
FileEntryHandle.
(setTopDir): Removed.
(getTopDir): Removed.
* src/BtContext.h: New file.
* src/DefaultPeerStorage.h: New file.
* src/PieceMessage.h (TorrentMan.h): Removed.
* src/RequestMessage.h (TorrentMan.h): Removed.
* src/TorrentDownloadEngine.h
(uploadLength): New variable.
(btContext): New variable.
(btRuntime): New variable.
(pieceStorage): New variable.
(peerStorage): New variable.
(btAnnounce): New variable.
(btProgressInfoFile): New variable.
(torrentMan): Removed.
(setBtContext): New function.
* src/TorrentDownloadEngine.cc: Use BtContext, BtRuntime,
pieceStorage,
peerStorage, btAnnounce, btProgressInfoFile.
* src/Piece.h
(toString): New function.
(Pieces): New type definition.
* src/Peer.h
(active): New variable.
(Peer): Added active.
(activate): Set active to true.
(deactivate): Set active to false.
(isActive): New function.
(Peers): New type definition.
* src/DirectDiskAdaptor.cc
(getFilePath): Use the accessor methods of FileEntry.
* src/TorrentConsoleDownloadEngine.h
(afterEachIteration): New function.
* src/TorrentConsoleDownloadEngine.cc
(haltRequested): New variable.
(sendStatistics): Use pieceStorage, btRuntime.
(afterEachIteration): New function.
* src/AnnounceList: AnnounceTier->AnnounceTierHandle.
* src/Directry.h
(Directory): New function.
(DirectoryHandle): New type definition.
* src/BtProgressInfoFile.h: New file.
* src/RequestMessage.cc: Use pieceStorage.
* src/BtRuntime.h: New file.
* src/DefaultBtContext.cc: New file.
* src/BitfieldMan.h
(getCompletedLength): New function(private).
(getCompletedLength): New function.
(getFilteredCompletedLength): New function.
* src/BitfieldMan.h
(getCompletedLength): New function(private).
(getCompletedLength): New function.
(getFilteredCompletedLength): New function.
* src/MultiDiskAdaptor.cc
(mkdir): New function.
(openFile): Call mkdir().
(initAndOpenFile): Call mkdir().
* src/CancelMessage.h
(TorrentMan.h): Removed.
* src/RejectMessage.h
(TorrentMan.h): Removed.
* src/DownloadEngineFactory.cc
(DefaultPieceStorage.h): New include.
(DefaultPeerStorage.h): New include.
(DefaultBtAnnounce.h): New include.
(DefaultBtProgressInfoFile.h): New include.
(newTorrentConsoleEngine): Rewritten.
* src/ShareRatioSeedCriteria.h
(torrentMan): Removed.
(btContext): New variable.
(peerStorage): New variable.
(btRuntime): New variable.
(evaluate): Use btContext, btRuntime, peerStorage.
* src/AnnounceTier.h: New file.
* src/BtAnnounce.h: New file.
* src/BtRegistry.h: New file.
* src/PeerInitiateConnectionCommand.h: Added btContext.
* src/PeerConnection.h (TorrentMan.h): Removed.
* src/PeerMessageFactory.cc: Use btContext, pieceStorage.
* src/Util.h
(slice): Added an argument.
* src/Util.cc
(slice): Added an argument to control whether trim is made or
not.
* src/PeerStorage.h: New file.
* src/BtRegistry.cc: New file.
* src/TrackerUpdateCommand.h: Made subclass of
BtContextAwareCommand.
* src/CopyDiskAdaptor.cc: Use the accessor methods of FileEntry.
* src/MultiDiskWriter.h: FileEntry -> FileEntryHandle
* src/PeerListenCommand.cc: Use btRuntime, peerStorage,
btContext.
* src/TorrentRequestInfo.h
(e): Removed.
(showFileEntry): Added an argument.
(getDownloadEngine): Return 0.
* src/DefaultBtAnnounce.h: New file.
* src/TorrentAutoSaveCommand.cc: Use btRuntime,
btProgressInfoFile.
* src/TrackerWatcherComand.cc: Use btRuntime, btAnnounce,
* src/PeerMessageFactory.h
(btContext): New variable.
(pieceStorage): New variable.
* src/TrackerUpdateCommand.cc: Use btRuntime, peerStorage,
btContext,
btAnnounce.
* src/DiskAdaptor.cc
(DiskAdaptor): Removed topDir.
(~DiskAdaptor): Removed topDir.
* src/PeerListenCommand.h: Made subclass of
BtContextAwareCommand.
* src/SeedCheckCommand.h: Made subclass of
BtContextAwareCommand.
* src/File.h (mkdirs): New function.
* src/DefaultPeerStorage): New file.
* src/DownloadEngineFactory.h
(newTorrentConsoleEngine): Use btContext.
* src/BtContextAwareCommand.cc: New file.
* src/PeerInitiateConnectionCommand.cc: Use btRuntime,
peerStorage.
* src/PeerMessage.h
(btContext): New variable.
(peerStorage): New variable.
(pieceStorage): New variable.
(setBtContext): New function.
* src/Directry.cc
(Directory): New function.
(createDir): Do nothing if name.size() == 0.
* src/AnnounceList.h
(AnnounceTier): Removed.
(AnnounceTiers): Removed.
* src/DefaultPieceStorage.h: New file.
* src/Piece.cc (toString): New function.
To fix typo:
* src/main.cc (showVersion): Fixed typo.
To fix compile warning:
* src/DelegatingPeerListProcessor.cc
(canHandle): Added "return false".
Diffstat (limited to 'src')
95 files changed, 3693 insertions, 432 deletions
diff --git a/src/AnnounceList.cc b/src/AnnounceList.cc index 43d0daa7..fbe8025a 100644 --- a/src/AnnounceList.cc +++ b/src/AnnounceList.cc @@ -59,7 +59,7 @@ void AnnounceList::reconfigure(const MetaEntry* announceListEntry) { urls.push_back(data->toString()); } if(urls.size()) { - AnnounceTier tier(urls); + AnnounceTierHandle tier(new AnnounceTier(urls)); tiers.push_back(tier); } } @@ -70,14 +70,14 @@ void AnnounceList::reconfigure(const MetaEntry* announceListEntry) { void AnnounceList::reconfigure(const string& url) { Strings urls; urls.push_back(url); - tiers.push_back(AnnounceTier(urls)); + tiers.push_back(AnnounceTierHandle(new AnnounceTier(urls))); resetIterator(); } void AnnounceList::resetIterator() { currentTier = tiers.begin(); - if(currentTier != tiers.end() && currentTier->urls.size()) { - currentTracker = currentTier->urls.begin(); + if(currentTier != tiers.end() && (*currentTier)->urls.size()) { + currentTracker = (*currentTier)->urls.begin(); currentTrackerInitialized = true; } else { currentTrackerInitialized = false; @@ -94,31 +94,31 @@ string AnnounceList::getAnnounce() const { void AnnounceList::announceSuccess() { if(currentTrackerInitialized) { - currentTier->nextEvent(); + (*currentTier)->nextEvent(); string url = *currentTracker; - currentTier->urls.erase(currentTracker); - currentTier->urls.push_front(url); + (*currentTier)->urls.erase(currentTracker); + (*currentTier)->urls.push_front(url); currentTier = tiers.begin(); - currentTracker = currentTier->urls.begin(); + currentTracker = (*currentTier)->urls.begin(); } } void AnnounceList::announceFailure() { if(currentTrackerInitialized) { currentTracker++; - if(currentTracker == currentTier->urls.end()) { + if(currentTracker == (*currentTier)->urls.end()) { currentTier++; if(currentTier == tiers.end()) { currentTier = tiers.begin(); } - currentTracker = currentTier->urls.begin(); + currentTracker = (*currentTier)->urls.begin(); } } } AnnounceTier::AnnounceEvent AnnounceList::getEvent() const { if(currentTrackerInitialized) { - return currentTier->event; + return (*currentTier)->event; } else { return AnnounceTier::STARTED; } @@ -126,13 +126,13 @@ AnnounceTier::AnnounceEvent AnnounceList::getEvent() const { void AnnounceList::setEvent(AnnounceTier::AnnounceEvent event) { if(currentTrackerInitialized) { - currentTier->event = event; + (*currentTier)->event = event; } } string AnnounceList::getEventString() const { if(currentTrackerInitialized) { - switch(currentTier->event) { + switch((*currentTier)->event) { case AnnounceTier::STARTED: case AnnounceTier::STARTED_AFTER_COMPLETION: return "started"; @@ -150,8 +150,8 @@ string AnnounceList::getEventString() const { class FindStoppedAllowedTier { public: - bool operator()(const AnnounceTier& tier) const { - switch(tier.event) { + bool operator()(const AnnounceTierHandle& tier) const { + switch(tier->event) { case AnnounceTier::DOWNLOADING: case AnnounceTier::STOPPED: case AnnounceTier::COMPLETED: @@ -165,8 +165,8 @@ public: class FindCompletedAllowedTier { public: - bool operator()(const AnnounceTier& tier) const { - switch(tier.event) { + bool operator()(const AnnounceTierHandle& tier) const { + switch(tier->event) { case AnnounceTier::DOWNLOADING: case AnnounceTier::COMPLETED: return true; @@ -187,7 +187,7 @@ int AnnounceList::countCompletedAllowedTier() const { void AnnounceList::setCurrentTier(const AnnounceTiers::iterator& itr) { if(itr != tiers.end()) { currentTier = itr; - currentTracker = currentTier->urls.begin(); + currentTracker = (*currentTier)->urls.begin(); } } @@ -220,6 +220,7 @@ void AnnounceList::moveToCompletedAllowedTier() { void AnnounceList::shuffle() { for(AnnounceTiers::iterator itr = tiers.begin(); itr != tiers.end(); itr++) { - random_shuffle(itr->urls.begin(), itr->urls.end()); + Strings& urls = (*itr)->urls; + random_shuffle(urls.begin(), urls.end()); } } diff --git a/src/AnnounceList.h b/src/AnnounceList.h index d2ecb3d8..fdd19a49 100644 --- a/src/AnnounceList.h +++ b/src/AnnounceList.h @@ -37,45 +37,7 @@ #include "common.h" #include "MetaEntry.h" - -class AnnounceTier { -public: - enum AnnounceEvent { - STARTED, - STARTED_AFTER_COMPLETION, - DOWNLOADING, - STOPPED, - COMPLETED, - SEEDING, - HALTED - }; - - AnnounceEvent event; - Strings urls; - - AnnounceTier(const Strings& urls):event(STARTED), urls(urls) {} - - void nextEvent() { - switch(event) { - case STARTED: - event = DOWNLOADING; - break; - case STARTED_AFTER_COMPLETION: - event = SEEDING; - break; - case STOPPED: - event = HALTED; - break; - case COMPLETED: - event = SEEDING; - break; - default: - break; - } - } -}; - -typedef deque<AnnounceTier> AnnounceTiers; +#include "AnnounceTier.h" class AnnounceList { public: diff --git a/src/AnnounceTier.h b/src/AnnounceTier.h new file mode 100644 index 00000000..85fdc27b --- /dev/null +++ b/src/AnnounceTier.h @@ -0,0 +1,80 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#ifndef _D_ANNOUNCE_TIER_H_ +#define _D_ANNOUNCE_TIER_H_ + +#include "common.h" + +class AnnounceTier { +public: + enum AnnounceEvent { + STARTED, + STARTED_AFTER_COMPLETION, + DOWNLOADING, + STOPPED, + COMPLETED, + SEEDING, + HALTED + }; + + AnnounceEvent event; + Strings urls; + + AnnounceTier(const Strings& urls):event(STARTED), urls(urls) {} + + void nextEvent() { + switch(event) { + case STARTED: + event = DOWNLOADING; + break; + case STARTED_AFTER_COMPLETION: + event = SEEDING; + break; + case STOPPED: + event = HALTED; + break; + case COMPLETED: + event = SEEDING; + break; + default: + break; + } + } +}; + +typedef SharedHandle<AnnounceTier> AnnounceTierHandle; +typedef deque<AnnounceTierHandle> AnnounceTiers; + +#endif // _D_ANNOUNCE_TIER_H_ diff --git a/src/BitfieldMan.cc b/src/BitfieldMan.cc index c05f2826..736bc5b8 100644 --- a/src/BitfieldMan.cc +++ b/src/BitfieldMan.cc @@ -510,13 +510,17 @@ long long int BitfieldMan::getFilteredTotalLength() const { } } -long long int BitfieldMan::getCompletedLength() const { +long long int BitfieldMan::getCompletedLength(bool useFilter) const { unsigned char* temp = new unsigned char[bitfieldLength]; - for(int i = 0; i < bitfieldLength; i++) { - temp[i] = bitfield[i]; - if(filterEnabled) { - temp[i] &= filterBitfield[i]; + if(useFilter) { + for(int i = 0; i < bitfieldLength; i++) { + temp[i] = bitfield[i]; + if(filterEnabled) { + temp[i] &= filterBitfield[i]; + } } + } else { + memcpy(temp, bitfield, bitfieldLength); } int completedBlocks = countSetBit(temp, bitfieldLength); long long int completedLength = 0; @@ -532,3 +536,11 @@ long long int BitfieldMan::getCompletedLength() const { delete [] temp; return completedLength; } + +long long int BitfieldMan::getCompletedLength() const { + return getCompletedLength(false); +} + +long long int BitfieldMan::getFilteredCompletedLength() const { + return getCompletedLength(true); +} diff --git a/src/BitfieldMan.h b/src/BitfieldMan.h index 2760c382..53758601 100644 --- a/src/BitfieldMan.h +++ b/src/BitfieldMan.h @@ -59,6 +59,8 @@ private: int getStartIndex(int index) const; int getEndIndex(int index) const; + + long long int getCompletedLength(bool useFilter) const; public: BitfieldMan(int blockLength, long long int totalLength); BitfieldMan(const BitfieldMan& bitfieldMan); @@ -191,11 +193,15 @@ public: void enableFilter(); void disableFilter(); bool isFilterEnabled() const; - long long int getFilteredTotalLength() const; /** * affected by filter */ + long long int getFilteredTotalLength() const; long long int getCompletedLength() const; + /** + * affected by filter + */ + long long int getFilteredCompletedLength() const; }; #endif // _D_BITFIELD_MAN_H_ diff --git a/src/BtAnnounce.h b/src/BtAnnounce.h new file mode 100644 index 00000000..3b9e735f --- /dev/null +++ b/src/BtAnnounce.h @@ -0,0 +1,111 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#ifndef _D_BT_ANNOUNCE_H_ +#define _D_BT_ANNOUNCE_H_ + +#include "common.h" + +class BtAnnounce { +public: + virtual ~BtAnnounce() {} + + /** + * Returns true if announce is required. + * Otherwise returns false. + * + * There are 4 announce timings: + * 1) started: when a download just started. + * 2) stopped: when the client quits. + * 3) completed: when a download just completed. + * 4) When a certain amount of time, aka announce interval, specified by + * a tracker, is elapsed. + */ + virtual bool isAnnounceReady() = 0; + + /** + * Returns announe URL with all necessary parameters included. + */ + virtual string getAnnounceUrl() = 0; + + /** + * Tells that the announce process has just started. + */ + virtual void announceStart() = 0; + + /** + * Tells that the announce succeeded. + */ + virtual void announceSuccess() = 0; + + /** + * Tells that the announce failed. + */ + virtual void announceFailure() = 0; + + /** + * Returns true if all announce attempt failed. + */ + virtual bool isAllAnnounceFailed() = 0; + + /** + * Resets announce status. + */ + virtual void resetAnnounce() = 0; + + /** + * Processes the repsponse from the tracker. + */ + virtual void processAnnounceResponse(const char* trackerResponse, + size_t trackerResponseLength) = 0; + + /** + * Returns true if no more announce is needed. + */ + virtual bool noMoreAnnounce() = 0; + + /** + * Shuffles the URLs in each announce tier. + */ + virtual void shuffleAnnounce() = 0; + + /** + * Returns the peer id of the client. + */ + virtual string getPeerId() = 0; +}; + +typedef SharedHandle<BtAnnounce> BtAnnounceHandle; + +#endif // _D_BT_ANNOUNCE_H_ diff --git a/src/BtContext.h b/src/BtContext.h new file mode 100644 index 00000000..ad05c4f8 --- /dev/null +++ b/src/BtContext.h @@ -0,0 +1,84 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#ifndef _D_BT_CONTEXT_H_ +#define _D_BT_CONTEXT_H_ + +#include "common.h" +#include "FileEntry.h" +#include "AnnounceTier.h" + +#define INFO_HASH_LENGTH 20 +#define MAX_PEER_ERROR 5 +#define MAX_PEERS 55 + +typedef deque<AnnounceTierHandle> AnnounceTiers; + +class BtContext { +public: + virtual ~BtContext() {} + + enum FILE_MODE { + SINGLE, + MULTI + }; + + virtual const unsigned char* getInfoHash() const = 0; + + virtual int getInfoHashLength() const = 0; + + virtual string getInfoHashAsString() const = 0; + + virtual string getPieceHash(int index) const = 0; + + virtual long long int getTotalLength() const = 0; + + virtual FILE_MODE getFileMode() const = 0; + + virtual FileEntries getFileEntries() const = 0; + + virtual AnnounceTiers getAnnounceTiers() const = 0; + + virtual void load(const string& torrentFile) = 0; + + virtual string getName() const = 0; + + virtual int getPieceLength() const = 0; + + virtual int getNumPieces() const = 0; +}; + +typedef SharedHandle<BtContext> BtContextHandle; + +#endif // _D_BT_CONTEXT_H_ diff --git a/src/BtContextAwareCommand.cc b/src/BtContextAwareCommand.cc new file mode 100644 index 00000000..b45d6ddc --- /dev/null +++ b/src/BtContextAwareCommand.cc @@ -0,0 +1,48 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#include "BtContextAwareCommand.h" +#include "BtRegistry.h" + +BtContextAwareCommand::BtContextAwareCommand(int cuid, + const BtContextHandle& btContext): + Command(cuid), + btContext(btContext), + btRuntime(BT_RUNTIME(btContext)), + pieceStorage(PIECE_STORAGE(btContext)), + peerStorage(PEER_STORAGE(btContext)), + btAnnounce(BT_ANNOUNCE(btContext)), + btProgressInfoFile(BT_PROGRESS_INFO_FILE(btContext)) {} + +BtContextAwareCommand::~BtContextAwareCommand() {} diff --git a/src/BtContextAwareCommand.h b/src/BtContextAwareCommand.h new file mode 100644 index 00000000..44bbd9b6 --- /dev/null +++ b/src/BtContextAwareCommand.h @@ -0,0 +1,60 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#ifndef _D_BT_CONTEXT_AWARE_COMMAND_H_ +#define _D_BT_CONTEXT_AWARE_COMMAND_H_ + +#include "Command.h" +#include "BtContext.h" +#include "BtRuntime.h" +#include "PieceStorage.h" +#include "PeerStorage.h" +#include "BtAnnounce.h" +#include "BtProgressInfoFile.h" + +class BtContextAwareCommand : public Command { +protected: + BtContextHandle btContext; + BtRuntimeHandle btRuntime; + PieceStorageHandle pieceStorage; + PeerStorageHandle peerStorage; + BtAnnounceHandle btAnnounce; + BtProgressInfoFileHandle btProgressInfoFile; +public: + BtContextAwareCommand(int cuid, const BtContextHandle& btContext); + + virtual ~BtContextAwareCommand(); +}; + +#endif // _D_BT_CONTEXT_AWARE_COMMAND_H_ diff --git a/src/BtProgressInfoFile.h b/src/BtProgressInfoFile.h new file mode 100644 index 00000000..e4d8f2ff --- /dev/null +++ b/src/BtProgressInfoFile.h @@ -0,0 +1,59 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#ifndef _D_BT_PROGRESS_INFO_FILE_H_ +#define _D_BT_PROGRESS_INFO_FILE_H_ + +#include "common.h" + +class BtProgressInfoFile { +public: + virtual ~BtProgressInfoFile() {} + + virtual string getFilename() = 0; + + virtual void setFilename(const string& filename) = 0; + + virtual bool exists() = 0; + + virtual void save() = 0; + + virtual void load() = 0; + + virtual void removeFile() = 0; +}; + +typedef SharedHandle<BtProgressInfoFile> BtProgressInfoFileHandle; + +#endif // _D_BT_PROGRESS_INFO_FILE_H_ diff --git a/src/BtRegistry.cc b/src/BtRegistry.cc new file mode 100644 index 00000000..cdd9c6e6 --- /dev/null +++ b/src/BtRegistry.cc @@ -0,0 +1,130 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#include "BtRegistry.h" +#include "DlAbortEx.h" + +PeerStorageMap BtRegistry::peerStorageMap; +PieceStorageMap BtRegistry::pieceStorageMap; +BtAnnounceMap BtRegistry::btAnnounceMap; +BtRuntimeMap BtRegistry::btRuntimeMap; +BtProgressInfoFileMap BtRegistry::btProgressInfoFileMap; + +PeerStorageHandle BtRegistry::getPeerStorage(const string& key) { + PeerStorageMap::iterator itr = peerStorageMap.find(key); + if(itr == peerStorageMap.end()) { + return PeerStorageHandle(0); + } else { + return itr->second; + } +} + +bool BtRegistry::registerPeerStorage(const string& key, + const PeerStorageHandle& peerStorage) { + PeerStorageMap::value_type p(key, peerStorage); + pair<PeerStorageMap::iterator, bool> retval = peerStorageMap.insert(p); + return retval.second; +} + +PieceStorageHandle +BtRegistry::getPieceStorage(const string& key) { + PieceStorageMap::iterator itr = pieceStorageMap.find(key); + if(itr == pieceStorageMap.end()) { + return PieceStorageHandle(0); + } else { + return itr->second; + } +} + +bool +BtRegistry::registerPieceStorage(const string& key, + const PieceStorageHandle& pieceStorage) { + PieceStorageMap::value_type p(key, pieceStorage); + pair<PieceStorageMap::iterator, bool> retval = pieceStorageMap.insert(p); + return retval.second; +} + +BtRuntimeHandle BtRegistry::getBtRuntime(const string& key) { + BtRuntimeMap::iterator itr = btRuntimeMap.find(key); + if(itr == btRuntimeMap.end()) { + return BtRuntimeHandle(0); + } else { + return itr->second; + } +} + +bool +BtRegistry::registerBtRuntime(const string& key, + const BtRuntimeHandle& btRuntime) { + BtRuntimeMap::value_type p(key, btRuntime); + pair<BtRuntimeMap::iterator, bool> retval = + btRuntimeMap.insert(p); + return retval.second; +} + +BtAnnounceHandle BtRegistry::getBtAnnounce(const string& key) { + BtAnnounceMap::iterator itr = btAnnounceMap.find(key); + if(itr == btAnnounceMap.end()) { + return BtAnnounceHandle(0); + } else { + return itr->second; + } +} + +bool +BtRegistry::registerBtAnnounce(const string& key, + const BtAnnounceHandle& btAnnounce) { + BtAnnounceMap::value_type p(key, btAnnounce); + pair<BtAnnounceMap::iterator, bool> retval = + btAnnounceMap.insert(p); + return retval.second; +} + +BtProgressInfoFileHandle BtRegistry::getBtProgressInfoFile(const string& key) { + BtProgressInfoFileMap::iterator itr = btProgressInfoFileMap.find(key); + if(itr == btProgressInfoFileMap.end()) { + return BtProgressInfoFileHandle(0); + } else { + return itr->second; + } +} + +bool +BtRegistry::registerBtProgressInfoFile(const string& key, + const BtProgressInfoFileHandle& btProgressInfoFile) { + BtProgressInfoFileMap::value_type p(key, btProgressInfoFile); + pair<BtProgressInfoFileMap::iterator, bool> retval = + btProgressInfoFileMap.insert(p); + return retval.second; +} diff --git a/src/BtRegistry.h b/src/BtRegistry.h new file mode 100644 index 00000000..f8356a23 --- /dev/null +++ b/src/BtRegistry.h @@ -0,0 +1,98 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#ifndef _D_BT_REGISTRY_H_ +#define _D_BT_REGISTRY_H_ + +#include "common.h" +#include "PeerStorage.h" +#include "PieceStorage.h" +#include "BtAnnounce.h" +#include "BtRuntime.h" +#include "BtProgressInfoFile.h" +#include <map> + +typedef map<string, PeerStorageHandle> PeerStorageMap; +typedef map<string, PieceStorageHandle> PieceStorageMap; +typedef map<string, BtAnnounceHandle> BtAnnounceMap; +typedef map<string, BtRuntimeHandle> BtRuntimeMap; +typedef map<string, BtProgressInfoFileHandle> BtProgressInfoFileMap; + +class BtRegistry { +private: + BtRegistry() {} + + static PeerStorageMap peerStorageMap; + static PieceStorageMap pieceStorageMap; + static BtAnnounceMap btAnnounceMap; + static BtRuntimeMap btRuntimeMap; + static BtProgressInfoFileMap btProgressInfoFileMap; +public: + static PeerStorageHandle getPeerStorage(const string& key); + static bool registerPeerStorage(const string& key, + const PeerStorageHandle& peer); + + static PieceStorageHandle getPieceStorage(const string& key); + static bool registerPieceStorage(const string& key, + const PieceStorageHandle& pieceStorage); + + static BtRuntimeHandle getBtRuntime(const string& key); + static bool registerBtRuntime(const string& key, + const BtRuntimeHandle& btRuntime); + + static BtAnnounceHandle getBtAnnounce(const string& key); + static bool registerBtAnnounce(const string& key, + const BtAnnounceHandle& btAnnounce); + + static BtProgressInfoFileHandle getBtProgressInfoFile(const string& key); + static bool registerBtProgressInfoFile(const string& key, + const BtProgressInfoFileHandle& btProgressInfoFile); +}; + +#define PEER_STORAGE(btContext) \ +BtRegistry::getPeerStorage(btContext->getInfoHashAsString()) + +#define PIECE_STORAGE(btContext) \ +BtRegistry::getPieceStorage(btContext->getInfoHashAsString()) + +#define BT_ANNOUNCE(btContext) \ +BtRegistry::getBtAnnounce(btContext->getInfoHashAsString()) + +#define BT_RUNTIME(btContext) \ +BtRegistry::getBtRuntime(btContext->getInfoHashAsString()) + +#define BT_PROGRESS_INFO_FILE(btContext) \ +BtRegistry::getBtProgressInfoFile(btContext->getInfoHashAsString()) + +#endif // _D_BT_REGISTRY_H_ diff --git a/src/BtRuntime.h b/src/BtRuntime.h new file mode 100644 index 00000000..911fa6d3 --- /dev/null +++ b/src/BtRuntime.h @@ -0,0 +1,94 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#ifndef _D_BT_RUNTIME_H_ +#define _D_BT_RUNTIME_H_ + +#include "common.h" +#include "SharedHandle.h" + +#define MIN_PEERS 15 + +class BtRuntime { +private: + long long int uploadLengthAtStartup; + int port; + bool halt; + int connections; + int cuidCounter; +public: + BtRuntime(): + uploadLengthAtStartup(0), + port(0), + halt(false), + connections(0), + cuidCounter(0) {} + ~BtRuntime() {} + + long long int getUploadLengthAtStartup() const { + return uploadLengthAtStartup; + } + + void setUploadLengthAtStartup(long long int length) { + this->uploadLengthAtStartup = length; + } + + void setListenPort(int port) { + this->port = port; + } + + int getListenPort() const { return port; } + + bool isHalt() const { return halt; } + + void setHalt(bool halt) { + this->halt = halt; + } + + int getConnections() const { return connections; } + + void increaseConnections() { connections++; } + + void decreaseConnections() { connections--; } + + bool lessThanMinPeer() const { return connections < MIN_PEERS; } + + bool lessThanEqMinPeer() const { return connections <= MIN_PEERS; } + + int getNewCuid() { return ++cuidCounter; } +}; + +typedef SharedHandle<BtRuntime> BtRuntimeHandle; + +#endif // _D_BT_RUNTIME_H_ diff --git a/src/CancelMessage.h b/src/CancelMessage.h index 1511d82a..b1a15281 100644 --- a/src/CancelMessage.h +++ b/src/CancelMessage.h @@ -36,7 +36,6 @@ #define _D_CANCEL_MESSAGE_H_ #include "SimplePeerMessage.h" -#include "TorrentMan.h" class CancelMessage : public SimplePeerMessage { private: diff --git a/src/CookieBox.cc b/src/CookieBox.cc index 5ec2abf3..42010121 100644 --- a/src/CookieBox.cc +++ b/src/CookieBox.cc @@ -68,7 +68,7 @@ void CookieBox::setField(Cookie& cookie, const string& name, const string& value void CookieBox::parse(Cookie& cookie, const string& cookieStr) const { cookie.clear(); Strings terms; - Util::slice(terms, cookieStr, ';'); + Util::slice(terms, cookieStr, ';', true); for(Strings::iterator itr = terms.begin(); itr != terms.end(); itr++) { pair<string, string> nv; Util::split(nv, *itr, '='); diff --git a/src/CopyDiskAdaptor.cc b/src/CopyDiskAdaptor.cc index 5318d5c4..c39d8f8a 100644 --- a/src/CopyDiskAdaptor.cc +++ b/src/CopyDiskAdaptor.cc @@ -46,19 +46,17 @@ void CopyDiskAdaptor::onDownloadComplete() { } void CopyDiskAdaptor::fixFilename() { - if(topDir != NULL) { - topDir->createDir(storeDir, true); - } long long int offset = 0; for(FileEntries::iterator itr = fileEntries.begin(); itr != fileEntries.end(); itr++) { - if(!itr->extracted && itr->requested) { - string dest = storeDir+"/"+itr->path; + if(!(*itr)->isExtracted() && (*itr)->isRequested()) { + (*itr)->setupDir(storeDir); + string dest = storeDir+"/"+(*itr)->getPath(); logger->info("writing file %s", dest.c_str()); - Util::rangedFileCopy(dest, getFilePath(), offset, itr->length); - itr->extracted = true; + Util::rangedFileCopy(dest, getFilePath(), offset, (*itr)->getLength()); + (*itr)->setExtracted(true); } - offset += itr->length; + offset += (*itr)->getLength(); } } diff --git a/src/DefaultBtAnnounce.cc b/src/DefaultBtAnnounce.cc new file mode 100644 index 00000000..04e069eb --- /dev/null +++ b/src/DefaultBtAnnounce.cc @@ -0,0 +1,246 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#include "DefaultBtAnnounce.h" +#include "BtRegistry.h" +#include "LogFactory.h" +#include "MetaFileUtil.h" +#include "Dictionary.h" +#include "List.h" +#include "Data.h" +#include "DelegatingPeerListProcessor.h" +#include "Util.h" +#include "prefs.h" +#include "DlAbortEx.h" +#include "message.h" + +DefaultBtAnnounce::DefaultBtAnnounce(BtContextHandle btContext, + const Option* option): + btContext(btContext), + trackers(0), + interval(DEFAULT_ANNOUNCE_INTERVAL), + minInterval(DEFAULT_ANNOUNCE_INTERVAL), + complete(0), + incomplete(0), + announceList(btContext->getAnnounceTiers()), + trackerNumTry(0), + option(option), + btRuntime(BT_RUNTIME(btContext)), + pieceStorage(PIECE_STORAGE(btContext)), + peerStorage(PEER_STORAGE(btContext)) +{ + prevAnnounceTime.setTimeInSec(0); + key = generateKey(); + peerId = generatePeerId(); + logger = LogFactory::getInstance(); +} + +DefaultBtAnnounce::~DefaultBtAnnounce() { +} + +string DefaultBtAnnounce::generateKey() const { + return Util::randomAlpha(8); +} + +string DefaultBtAnnounce::generatePeerId() const { + string peerId = "-aria2-"; + peerId += Util::randomAlpha(20-peerId.size()); + return peerId; +} + +bool DefaultBtAnnounce::isDefaultAnnounceReady() { + return (trackers == 0 && prevAnnounceTime.elapsed(minInterval)); +} + +bool DefaultBtAnnounce::isStoppedAnnounceReady() { + return (trackers == 0 && + btRuntime->isHalt() && + announceList.countStoppedAllowedTier()); +} + +bool DefaultBtAnnounce::isCompletedAnnounceReady() { + return (trackers == 0 && + pieceStorage->downloadFinished() && + announceList.countCompletedAllowedTier()); +} + +bool DefaultBtAnnounce::isAnnounceReady() { + return + isStoppedAnnounceReady() || + isCompletedAnnounceReady() || + isDefaultAnnounceReady(); +} + +string DefaultBtAnnounce::getAnnounceUrl() { + if(isStoppedAnnounceReady()) { + announceList.moveToStoppedAllowedTier(); + announceList.setEvent(AnnounceTier::STOPPED); + } else if(isCompletedAnnounceReady()) { + announceList.moveToCompletedAllowedTier(); + announceList.setEvent(AnnounceTier::COMPLETED); + } else if(isDefaultAnnounceReady()) { + // If download completed before "started" event is sent to a tracker, + // we change the event to something else to prevent us from + // sending "completed" event. + if(pieceStorage->downloadFinished() && + announceList.getEvent() == AnnounceTier::STARTED) { + announceList.setEvent(AnnounceTier::STARTED_AFTER_COMPLETION); + } + } + int numWant = 50; + if(!btRuntime->lessThanEqMinPeer() || + btRuntime->isHalt()) { + numWant = 0; + } + TransferStat stat = peerStorage->calculateStat(); + long long int left = pieceStorage->getTotalLength()-pieceStorage->getCompletedLength(); + if(left < 0) { + left = 0; + } + string url = announceList.getAnnounce()+"?"+ + "info_hash="+Util::torrentUrlencode(btContext->getInfoHash(), + btContext->getInfoHashLength())+"&"+ + "peer_id="+peerId+"&"+ + "port="+Util::itos(btRuntime->getListenPort())+"&"+ + "uploaded="+Util::llitos(stat.getSessionUploadLength())+"&"+ + "downloaded="+Util::llitos(stat.getSessionDownloadLength())+"&"+ + "left="+Util::llitos(left)+"&"+ + "compact=1"+"&"+ + "key="+key+"&"+ + "numwant="+Util::itos(numWant)+"&"+ + "no_peer_id=1"; + string event = announceList.getEventString(); + if(!event.empty()) { + url += string("&")+"event="+event; + } + if(!trackerId.empty()) { + url += string("&")+"trackerid="+Util::torrentUrlencode((const unsigned char*)trackerId.c_str(), + trackerId.size()); + } + return url; +} + +void DefaultBtAnnounce::announceStart() { + trackers++; +} + +void DefaultBtAnnounce::announceSuccess() { + trackers = 0; + announceList.announceSuccess(); +} + +void DefaultBtAnnounce::announceFailure() { + trackers = 0; + trackerNumTry++; + announceList.announceFailure(); +} + +bool DefaultBtAnnounce::isAllAnnounceFailed() { + return + trackerNumTry >= option->getAsInt(PREF_TRACKER_MAX_TRIES); +} + +void DefaultBtAnnounce::resetAnnounce() { + prevAnnounceTime.reset(); + trackerNumTry = 0; +} + +void +DefaultBtAnnounce::processAnnounceResponse(const char* trackerResponse, + size_t trackerResponseLength) +{ + SharedHandle<MetaEntry> entry(MetaFileUtil::bdecoding(trackerResponse, + trackerResponseLength)); + Dictionary* response = (Dictionary*)entry.get(); + Data* failureReasonData = (Data*)response->get("failure reason"); + if(failureReasonData) { + throw new DlAbortEx("Tracker returned failure reason: %s", + failureReasonData->toString().c_str()); + } + Data* warningMessageData = (Data*)response->get("warning message"); + if(warningMessageData) { + logger->warn(MSG_TRACKER_WARNING_MESSAGE, + warningMessageData->toString().c_str()); + } + Data* trackerIdData = (Data*)response->get("tracker id"); + if(trackerIdData) { + trackerId = trackerIdData->toString(); + logger->debug("Tracker ID:%s", trackerId.c_str()); + } + Data* intervalData = (Data*)response->get("interval"); + if(intervalData) { + interval = intervalData->toInt(); + logger->debug("Interval:%d", interval); + } + Data* minIntervalData = (Data*)response->get("min interval"); + if(minIntervalData) { + minInterval = minIntervalData->toInt(); + logger->debug("Min interval:%d", minInterval); + } + if(minInterval > interval) { + minInterval = interval; + } + Data* completeData = (Data*)response->get("complete"); + if(completeData) { + complete = completeData->toInt(); + logger->debug("Complete:%d", complete); + } + Data* incompleteData = (Data*)response->get("incomplete"); + if(incompleteData) { + incomplete = incompleteData->toInt(); + logger->debug("Incomplete:%d", incomplete); + } + const MetaEntry* peersEntry = response->get("peers"); + if(peersEntry && + !btRuntime->isHalt() && + btRuntime->lessThanMinPeer()) { + DelegatingPeerListProcessor proc(btContext->getPieceLength(), + btContext->getTotalLength()); + Peers peers = proc.extractPeer(peersEntry); + peerStorage->addPeer(peers); + } + if(!peersEntry) { + logger->info("No peer list received."); + } +} + +bool DefaultBtAnnounce::noMoreAnnounce() { + return (trackers == 0 && + btRuntime->isHalt() && + !announceList.countStoppedAllowedTier()); +} + +void DefaultBtAnnounce::shuffleAnnounce() { + announceList.shuffle(); +} diff --git a/src/DefaultBtAnnounce.h b/src/DefaultBtAnnounce.h new file mode 100644 index 00000000..f54c1ac9 --- /dev/null +++ b/src/DefaultBtAnnounce.h @@ -0,0 +1,122 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#ifndef _D_DEFAULT_BT_ANNOUNCE_H_ +#define _D_DEFAULT_BT_ANNOUNCE_H_ + +#include "BtAnnounce.h" +#include "BtContext.h" +#include "TimeA2.h" +#include "AnnounceList.h" +#include "Option.h" +#include "Logger.h" +#include "BtRuntime.h" +#include "PieceStorage.h" +#include "PeerStorage.h" + +#define DEFAULT_ANNOUNCE_INTERVAL 1800 + +class DefaultBtAnnounce : public BtAnnounce { +private: + BtContextHandle btContext; + int trackers; + Time prevAnnounceTime; + int interval; + int minInterval; + int complete; + int incomplete; + AnnounceList announceList; + string trackerId; + string key; + int trackerNumTry; + string peerId; + const Option* option; + Logger* logger; + BtRuntimeHandle btRuntime; + PieceStorageHandle pieceStorage; + PeerStorageHandle peerStorage; +public: + DefaultBtAnnounce(BtContextHandle btContext, const Option* option); + virtual ~DefaultBtAnnounce(); + + void setBtRuntime(const BtRuntimeHandle& btRuntime) { + this->btRuntime = btRuntime; + } + BtRuntimeHandle getBtRuntime() const { return btRuntime; } + + void setPieceStorage(const PieceStorageHandle& pieceStorage) { + this->pieceStorage = pieceStorage; + } + PieceStorageHandle getPieceStorage() const { return pieceStorage; } + + void setPeerStorage(const PeerStorageHandle& peerStorage) { + this->peerStorage = peerStorage; + } + PeerStorageHandle getPeerStorage() const { return peerStorage; } + + bool isDefaultAnnounceReady(); + + bool isStoppedAnnounceReady(); + + bool isCompletedAnnounceReady(); + + virtual bool isAnnounceReady(); + + virtual string getAnnounceUrl(); + + virtual void announceStart(); + + virtual void announceSuccess(); + + virtual void announceFailure(); + + virtual bool isAllAnnounceFailed(); + + virtual void resetAnnounce(); + + virtual void processAnnounceResponse(const char* trackerResponse, + size_t trackerResponseLength); + + virtual bool noMoreAnnounce(); + + virtual void shuffleAnnounce(); + + string generateKey() const; + + string generatePeerId() const; + + virtual string getPeerId() { return peerId; } +}; + +#endif // _D_DEFAULT_BT_ANNOUNCE_H_ diff --git a/src/DefaultBtContext.cc b/src/DefaultBtContext.cc new file mode 100644 index 00000000..1acf5fc5 --- /dev/null +++ b/src/DefaultBtContext.cc @@ -0,0 +1,237 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#include "DefaultBtContext.h" +#include "MetaFileUtil.h" +#include "Dictionary.h" +#include "List.h" +#include "Data.h" +#include "DlAbortEx.h" +#include "ShaVisitor.h" +#include "Util.h" + +DefaultBtContext::DefaultBtContext() {} + +DefaultBtContext::~DefaultBtContext() {} + +const unsigned char* DefaultBtContext::getInfoHash() const { + return infoHash; +} + +int DefaultBtContext::getInfoHashLength() const { + return INFO_HASH_LENGTH; +} + +string DefaultBtContext::getInfoHashAsString() const { + return infoHashString; +} + +void DefaultBtContext::clear() { + memset(infoHash, 0, INFO_HASH_LENGTH); + infoHashString = ""; + pieceHashes.clear(); + fileEntries.clear(); + totalLength = 0; + pieceLength = 0; + fileMode = BtContext::SINGLE; + numPieces = 0; + name = ""; + announceTiers.clear(); +} + +void DefaultBtContext::extractPieceHash(const unsigned char* hashData, + int hashDataLength, + int hashLength) { + assert(hashDataLength > 0); + assert(hashLength > 0); + int numPieces = hashDataLength/hashLength; + assert(numPieces > 0); + + for(int i = 0; i < numPieces; i++) { + pieceHashes.push_back(Util::toHex(&hashData[i*hashLength], + hashLength)); + } +} + +void DefaultBtContext::extractFileEntries(Dictionary* infoDic, + const string& defaultName) { + // TODO use dynamic_cast + Data* nameData = (Data*)infoDic->get("name"); + if(nameData) { + name = nameData->toString(); + } else { + char* basec = strdup(defaultName.c_str()); + name = string(basename(basec))+".file"; + free(basec); + } + // TODO use dynamic_cast + List* files = (List*)infoDic->get("files"); + if(files) { + long long int length = 0; + long long int offset = 0; + // multi-file mode + fileMode = BtContext::MULTI; + const MetaList& metaList = files->getList(); + for(MetaList::const_iterator itr = metaList.begin(); + itr != metaList.end(); itr++) { + Dictionary* fileDic = (Dictionary*)(*itr); + // TODO use dynamic_cast + Data* lengthData = (Data*)fileDic->get("length"); + length += lengthData->toLLInt(); + // TODO use dynamic_cast + List* pathList = (List*)fileDic->get("path"); + const MetaList& paths = pathList->getList(); + string path; + for(int i = 0; i < (int)paths.size()-1; i++) { + Data* subpath = (Data*)paths.at(i); + path += subpath->toString()+"/"; + } + // TODO use dynamic_cast + Data* lastPath = (Data*)paths.back(); + path += lastPath->toString(); + + FileEntryHandle fileEntry(new FileEntry(path, + lengthData->toLLInt(), + offset)); + fileEntries.push_back(fileEntry); + offset += fileEntry->getLength(); + } + totalLength = length; + } else { + // single-file mode; + fileMode = BtContext::SINGLE; + Data* length = (Data*)infoDic->get("length"); + totalLength = length->toLLInt(); + FileEntryHandle fileEntry(new FileEntry(name, totalLength, 0)); + fileEntries.push_back(fileEntry); + } +} + +void DefaultBtContext::extractAnnounce(Data* announceData) { + Strings urls; + urls.push_back(announceData->toString()); + announceTiers.push_back(AnnounceTierHandle(new AnnounceTier(urls))); +} + +void DefaultBtContext::extractAnnounceList(List* announceListData) { + for(MetaList::const_iterator itr = announceListData->getList().begin(); + itr != announceListData->getList().end(); itr++) { + const List* elem = (List*)*itr; + Strings urls; + for(MetaList::const_iterator elemItr = elem->getList().begin(); + elemItr != elem->getList().end(); elemItr++) { + const Data* data = (Data*)*elemItr; + urls.push_back(data->toString()); + } + if(urls.size()) { + AnnounceTierHandle tier(new AnnounceTier(urls)); + announceTiers.push_back(tier); + } + } +} + +void DefaultBtContext::load(const string& torrentFile) { + clear(); + MetaEntry* rootEntry = MetaFileUtil::parseMetaFile(torrentFile); + if(!dynamic_cast<Dictionary*>(rootEntry)) { + throw new DlAbortEx("torrent file does not contain a root dictionary ."); + } + SharedHandle<Dictionary> rootDic = + SharedHandle<Dictionary>((Dictionary*)rootEntry); + Dictionary* infoDic = (Dictionary*)rootDic->get("info"); + // retrieve infoHash + ShaVisitor v; + infoDic->accept(&v); + int len; + v.getHash(infoHash, len); + infoHashString = Util::toHex(infoHash, INFO_HASH_LENGTH); + // calculate the number of pieces + Data* pieceHashData = (Data*)infoDic->get("pieces"); + numPieces = pieceHashData->getLen()/PIECE_HASH_LENGTH; + // retrieve piece length + Data* pieceLengthData = (Data*)infoDic->get("piece length"); + pieceLength = pieceLengthData->toInt(); + // retrieve piece hashes + extractPieceHash((unsigned char*)pieceHashData->getData(), + pieceHashData->getLen(), + PIECE_HASH_LENGTH); + // retrieve file entries + extractFileEntries(infoDic, torrentFile); + // retrieve announce + Data* announceData = (Data*)rootDic->get("announce"); + List* announceListData = (List*)rootDic->get("announce-list"); + if(announceListData) { + extractAnnounceList(announceListData); + } else if(announceData) { + extractAnnounce(announceData); + } + if(!announceTiers.size()) { + throw new DlAbortEx("No announce URL found."); + } +} + +string DefaultBtContext::getPieceHash(int index) const { + if(index < 0 || numPieces <= index) { + return ""; + } + return pieceHashes.at(index); +} + +long long int DefaultBtContext::getTotalLength() const { + return totalLength; +} + +BtContext::FILE_MODE DefaultBtContext::getFileMode() const { + return fileMode; +} + +FileEntries DefaultBtContext::getFileEntries() const { + return fileEntries; +} + +AnnounceTiers DefaultBtContext::getAnnounceTiers() const { + return announceTiers; +} + +string DefaultBtContext::getName() const { + return name; +} + +int DefaultBtContext::getPieceLength() const { + return pieceLength; +} + +int DefaultBtContext::getNumPieces() const { + return numPieces; +} diff --git a/src/DefaultBtContext.h b/src/DefaultBtContext.h new file mode 100644 index 00000000..74bae247 --- /dev/null +++ b/src/DefaultBtContext.h @@ -0,0 +1,97 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#ifndef _D_DEFAULT_BT_CONTEXT_H_ +#define _D_DEFAULT_BT_CONTEXT_H_ + +#include "BtContext.h" +#include "Dictionary.h" +#include "Data.h" +#include "List.h" +#define INFO_HASH_LENGTH 20 +#define PIECE_HASH_LENGTH 20 + +typedef Strings PieceHashes; + +class DefaultBtContext : public BtContext { +private: + unsigned char infoHash[INFO_HASH_LENGTH]; + string infoHashString; + PieceHashes pieceHashes; + FileEntries fileEntries; + FILE_MODE fileMode; + long long int totalLength; + int pieceLength; + string name; + int numPieces; + AnnounceTiers announceTiers; + + void clear(); + void extractPieceHash(const unsigned char* hashData, + int hashDataLength, + int hashLength); + void extractFileEntries(Dictionary* infoDic, + const string& defaultName); + void extractAnnounce(Data* announceData); + void extractAnnounceList(List* announceListData); + public: + DefaultBtContext(); + virtual ~DefaultBtContext(); + + virtual const unsigned char* getInfoHash() const; + + virtual int getInfoHashLength() const; + + virtual string getInfoHashAsString() const; + + virtual string getPieceHash(int index) const; + + virtual long long int getTotalLength() const; + + virtual FILE_MODE getFileMode() const; + + virtual FileEntries getFileEntries() const; + + virtual AnnounceTiers getAnnounceTiers() const; + + virtual void load(const string& torrentFile); + + virtual string getName() const; + + virtual int getPieceLength() const; + + virtual int getNumPieces() const; +}; + +#endif // _D_DEFAULT_BT_CONTEXT_H_ diff --git a/src/DefaultBtProgressInfoFile.cc b/src/DefaultBtProgressInfoFile.cc new file mode 100644 index 00000000..a524a589 --- /dev/null +++ b/src/DefaultBtProgressInfoFile.cc @@ -0,0 +1,172 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#include "DefaultBtProgressInfoFile.h" +#include "BtRegistry.h" +#include "LogFactory.h" +#include "prefs.h" +#include "DlAbortEx.h" +#include "message.h" +#include "File.h" +#include "Util.h" +#include <errno.h> + +DefaultBtProgressInfoFile::DefaultBtProgressInfoFile(const BtContextHandle& btContext, + const Option* option): + btContext(btContext), + option(option), + pieceStorage(PIECE_STORAGE(btContext)), + btRuntime(BT_RUNTIME(btContext)), + peerStorage(PEER_STORAGE(btContext)) +{ + logger = LogFactory::getInstance(); + string storeDir = option->get(PREF_DIR); + filename = storeDir+"/"+btContext->getName()+".aria2"; +} + +DefaultBtProgressInfoFile::~DefaultBtProgressInfoFile() {} + +void DefaultBtProgressInfoFile::save() { + logger->info(MSG_SAVING_SEGMENT_FILE, filename.c_str()); + FILE* file = openFile(filename, "w"); + try { + if(fwrite(btContext->getInfoHash(), + btContext->getInfoHashLength(), 1, file) < 1) { + throw string("writeError:info hash"); + } + if(fwrite(pieceStorage->getBitfield(), + pieceStorage->getBitfieldLength(), 1, file) < 1) { + throw string("writeError:bitfield"); + } + TransferStat stat = peerStorage->calculateStat(); + long long int allTimeDownloadLength = pieceStorage->getCompletedLength(); + if(fwrite(&allTimeDownloadLength, + sizeof(allTimeDownloadLength), 1, file) < 1) { + throw string("writeError:download length"); + } + long long int allTimeUploadLength = + btRuntime->getUploadLengthAtStartup()+ + stat.getSessionUploadLength(); + if(fwrite(&allTimeUploadLength, + sizeof(allTimeUploadLength), 1, file) < 1) { + throw string("writeError:upload length"); + } + fclose(file); + logger->info(MSG_SAVED_SEGMENT_FILE); + } catch(string ex) { + fclose(file); + throw new DlAbortEx(EX_SEGMENT_FILE_WRITE, + filename.c_str(), strerror(errno)); + } +} + +void DefaultBtProgressInfoFile::load() { + logger->info(MSG_LOADING_SEGMENT_FILE, filename.c_str()); + FILE* file = openFile(filename, "r+"); + unsigned char* savedInfoHash = 0; + unsigned char* savedBitfield = 0; + try { + savedInfoHash = new unsigned char[btContext->getInfoHashLength()]; + savedBitfield = new unsigned char[pieceStorage->getBitfieldLength()]; + if(fread(savedInfoHash, btContext->getInfoHashLength(), 1, file) < 1) { + throw string("readError"); + } + if(Util::toHex(savedInfoHash, btContext->getInfoHashLength()) != + btContext->getInfoHashAsString()) { + throw new DlAbortEx("Incorrect infoHash."); + } + if(fread(savedBitfield, pieceStorage->getBitfieldLength(), 1, file) < 1) { + throw string("readError"); + } + pieceStorage->setBitfield(savedBitfield, + pieceStorage->getBitfieldLength()); + // allTimeDownloadLength exists for only a compatibility reason. + long long int allTimeDownloadLength; + if(fread(&allTimeDownloadLength, + sizeof(allTimeDownloadLength), 1, file) < 1) { + throw string("readError"); + } + long long int allTimeUploadLength; + if(fread(&allTimeUploadLength, + sizeof(allTimeUploadLength), 1, file) < 1) { + throw string("readError"); + } + btRuntime->setUploadLengthAtStartup(allTimeUploadLength); + delete [] savedBitfield; + savedBitfield = 0; + delete [] savedInfoHash; + savedInfoHash = 0; + fclose(file); + } catch(string ex) { + if(savedBitfield) { + delete [] savedBitfield; + } + if(savedInfoHash) { + delete [] savedInfoHash; + } + fclose(file); + throw new DlAbortEx(EX_SEGMENT_FILE_READ, + filename.c_str(), strerror(errno)); + } + logger->info(MSG_LOADED_SEGMENT_FILE); +} + +void DefaultBtProgressInfoFile::removeFile() { + if(exists()) { + File f(filename); + f.remove(); + } +} + +FILE* DefaultBtProgressInfoFile::openFile(const string& filename, + const string& mode) const +{ + FILE* file = fopen(filename.c_str(), mode.c_str()); + if(!file) { + throw new DlAbortEx(EX_SEGMENT_FILE_OPEN, + filename.c_str(), strerror(errno)); + } + return file; +} + +bool DefaultBtProgressInfoFile::exists() { + File f(filename); + if(f.isFile()) { + logger->info(MSG_SEGMENT_FILE_EXISTS, filename.c_str()); + return true; + } else { + logger->info(MSG_SEGMENT_FILE_DOES_NOT_EXIST, filename.c_str()); + return false; + } +} diff --git a/src/DefaultBtProgressInfoFile.h b/src/DefaultBtProgressInfoFile.h new file mode 100644 index 00000000..201900dd --- /dev/null +++ b/src/DefaultBtProgressInfoFile.h @@ -0,0 +1,92 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#ifndef _D_DEFAULT_BT_PROGRESS_INFO_FILE_H_ +#define _D_DEFAULT_BT_PROGRESS_INFO_FILE_H_ + +#include "BtProgressInfoFile.h" +#include "BtContext.h" +#include "PieceStorage.h" +#include "BtRuntime.h" +#include "PeerStorage.h" +#include "Logger.h" +#include "Option.h" + +class DefaultBtProgressInfoFile : public BtProgressInfoFile { +private: + BtContextHandle btContext; + const Option* option; + Logger* logger; + PieceStorageHandle pieceStorage; + BtRuntimeHandle btRuntime; + PeerStorageHandle peerStorage; + string filename; + + FILE* openFile(const string& filename, const string& mode) const; +public: + DefaultBtProgressInfoFile(const BtContextHandle& btContext, + const Option* option); + virtual ~DefaultBtProgressInfoFile(); + + void setBtRuntime(const BtRuntimeHandle& btRuntime) { + this->btRuntime = btRuntime; + } + BtRuntimeHandle getBtRuntime() const { return btRuntime; } + + void setPieceStorage(const PieceStorageHandle& pieceStorage) { + this->pieceStorage = pieceStorage; + } + PieceStorageHandle getPieceStorage() const { return pieceStorage; } + + void setPeerStorage(const PeerStorageHandle& peerStorage) { + this->peerStorage = peerStorage; + } + PeerStorageHandle getPeerStorage() const { return peerStorage; } + + virtual void setFilename(const string& filename) { + this->filename = filename; + } + virtual string getFilename() { return filename; } + + virtual bool exists(); + + virtual void save(); + + virtual void load(); + + virtual void removeFile(); + +}; + +#endif // _D_DEFAULT_BT_PROGRESS_INFO_FILE_H_ diff --git a/src/DefaultPeerStorage.cc b/src/DefaultPeerStorage.cc new file mode 100644 index 00000000..456f99f2 --- /dev/null +++ b/src/DefaultPeerStorage.cc @@ -0,0 +1,174 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#include "DefaultPeerStorage.h" +#include "LogFactory.h" +#include "BtRegistry.h" + +extern PeerHandle nullPeer; + +DefaultPeerStorage::DefaultPeerStorage(BtContextHandle btContext, + const Option* option): + btContext(btContext), + option(option), + maxPeerListSize(MAX_PEER_LIST_SIZE), + peerEntryIdCounter(0), + btRuntime(BT_RUNTIME(btContext)) +{ + logger = LogFactory::getInstance(); +} + +DefaultPeerStorage::~DefaultPeerStorage() {} + +bool DefaultPeerStorage::addPeer(const PeerHandle& peer) { + Peers::iterator itr = find(peers.begin(), peers.end(), peer); + if(itr == peers.end()) { + if(peers.size() >= (size_t)maxPeerListSize) { + deleteUnusedPeer(peers.size()-maxPeerListSize+1); + } + ++peerEntryIdCounter; + peer->entryId = peerEntryIdCounter; + peers.push_back(peer); + return true; + } else { + const PeerHandle& peer = *itr; + if(peer->error >= MAX_PEER_ERROR || peer->cuid != 0) { + return false; + } else { + *itr = peer; + return true; + } + } +} + +void DefaultPeerStorage::addPeer(const Peers& peers) { + for(Peers::const_iterator itr = peers.begin(); + itr != peers.end(); itr++) { + const PeerHandle& peer = *itr; + if(addPeer(peer)) { + logger->debug("Adding peer %s:%d", + peer->ipaddr.c_str(), peer->port); + } + } +} + +const Peers& DefaultPeerStorage::getPeers() { + return peers; +} + +class FindFinePeer { +public: + bool operator()(const PeerHandle& peer) const { + return peer->cuid == 0 && peer->error < MAX_PEER_ERROR; + } +}; + +PeerHandle DefaultPeerStorage::getUnusedPeer() { + Peers::const_iterator itr = find_if(peers.begin(), peers.end(), + FindFinePeer()); + if(itr == peers.end()) { + return nullPeer; + } else { + return *itr; + } +} + +class FindPeer { +private: + string ipaddr; + int port; +public: + FindPeer(const string& ipaddr, int port):ipaddr(ipaddr), port(port) {} + + bool operator()(const PeerHandle& peer) const { + return ipaddr == peer->ipaddr && port == peer->port; + } +}; + +PeerHandle DefaultPeerStorage::getPeer(const string& ipaddr, + int port) const { + Peers::const_iterator itr = find_if(peers.begin(), peers.end(), + FindPeer(ipaddr, port)); + if(itr == peers.end()) { + return nullPeer; + } else { + return *itr; + } +} + +int DefaultPeerStorage::countPeer() const { + return peers.size(); +} + +bool DefaultPeerStorage::isPeerAvailable() { + return getUnusedPeer() != nullPeer; +} + +Peers DefaultPeerStorage::getActivePeers() { + Peers activePeers; + for(Peers::iterator itr = peers.begin(); itr != peers.end(); itr++) { + PeerHandle& peer = *itr; + if(peer->isActive()) { + activePeers.push_back(peer); + } + } + return activePeers; +} + +TransferStat DefaultPeerStorage::calculateStat() { + TransferStat stat; + Peers activePeers = getActivePeers(); + for(Peers::iterator itr = activePeers.begin(); + itr != activePeers.end(); itr++) { + PeerHandle& peer = *itr; + stat.downloadSpeed += peer->calculateDownloadSpeed(); + stat.uploadSpeed += peer->calculateUploadSpeed(); + stat.sessionDownloadLength += peer->getSessionDownloadLength(); + stat.sessionUploadLength += peer->getSessionUploadLength(); + } + return stat; +} + +void DefaultPeerStorage::deleteUnusedPeer(int delSize) { + for(Peers::iterator itr = peers.begin(); + itr != peers.end() && delSize > 0;) { + const PeerHandle& p = *itr; + if(p->cuid == 0) { + itr = peers.erase(itr); + delSize--; + } else { + itr++; + } + } +} diff --git a/src/DefaultPeerStorage.h b/src/DefaultPeerStorage.h new file mode 100644 index 00000000..daabb69d --- /dev/null +++ b/src/DefaultPeerStorage.h @@ -0,0 +1,90 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#ifndef _D_DEFAULT_PEER_STORAGE_H_ +#define _D_DEFAULT_PEER_STORAGE_H_ + +#include "PeerStorage.h" +#include "BtContext.h" +#include "Option.h" +#include "Logger.h" +#include "BtRuntime.h" + +#define MAX_PEER_LIST_SIZE 100 +#define MAX_PEER_ERROR 5 + +class DefaultPeerStorage : public PeerStorage { +private: + BtContextHandle btContext; + const Option* option; + Peers peers; + int maxPeerListSize; + int peerEntryIdCounter; + Logger* logger; + BtRuntimeHandle btRuntime; +public: + DefaultPeerStorage(BtContextHandle btContext, const Option* option); + virtual ~DefaultPeerStorage(); + + void setBtRuntime(const BtRuntimeHandle& btRuntime) { + this->btRuntime = btRuntime; + } + BtRuntimeHandle getBtRuntime() const { return btRuntime; } + + virtual bool addPeer(const PeerHandle& peer); + + int countPeer() const; + + virtual PeerHandle getUnusedPeer(); + + PeerHandle getPeer(const string& ipaddr, int port) const; + + virtual void addPeer(const Peers& peers); + + virtual const Peers& getPeers(); + + virtual bool isPeerAvailable(); + + virtual Peers getActivePeers(); + + virtual TransferStat calculateStat(); + + void setMaxPeerListSize(int size) { this->maxPeerListSize = size; } + + int getMaxPeerListSize() const { return maxPeerListSize; } + + void deleteUnusedPeer(int delSize); +}; + +#endif // _D_DEFAULT_PEER_STORAGE_H_ diff --git a/src/DefaultPieceStorage.cc b/src/DefaultPieceStorage.cc new file mode 100644 index 00000000..c819934f --- /dev/null +++ b/src/DefaultPieceStorage.cc @@ -0,0 +1,433 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#include "DefaultPieceStorage.h" +#include "LogFactory.h" +#include "prefs.h" +#include "DirectDiskAdaptor.h" +#include "MultiDiskAdaptor.h" +#include "CopyDiskAdaptor.h" +#include "DefaultDiskWriter.h" +#include "MultiDiskWriter.h" +#include "PreAllocationDiskWriter.h" +#include "DlAbortEx.h" + +DefaultPieceStorage::DefaultPieceStorage(BtContextHandle btContext, const Option* option): + btContext(btContext), + endGamePieceNum(END_GAME_PIECE_NUM), + option(option) +{ + bitfieldMan = new BitfieldMan(btContext->getPieceLength(), + btContext->getTotalLength()); + logger = LogFactory::getInstance(); +} + +DefaultPieceStorage::~DefaultPieceStorage() { + delete bitfieldMan; +} + +bool DefaultPieceStorage::hasMissingPiece(const PeerHandle& peer) { + return bitfieldMan->hasMissingPiece(peer->getBitfield(), + peer->getBitfieldLength()); +} + +bool DefaultPieceStorage::isEndGame() { + return bitfieldMan->countMissingBlock() <= endGamePieceNum; +} + +int DefaultPieceStorage::getMissingPieceIndex(const PeerHandle& peer) { + int index = -1; + if(isEndGame()) { + index = bitfieldMan->getMissingIndex(peer->getBitfield(), + peer->getBitfieldLength()); + } else { + index = bitfieldMan->getMissingUnusedIndex(peer->getBitfield(), + peer->getBitfieldLength()); + } + return index; +} + +Piece DefaultPieceStorage::checkOutPiece(int index) { + if(index == -1) { + return Piece::nullPiece; + } + bitfieldMan->setUseBit(index); + + Piece piece = findUsedPiece(index); + if(Piece::isNull(piece)) { + Piece piece(index, bitfieldMan->getBlockLength(index)); + addUsedPiece(piece); + return piece; + } else { + return piece; + } +} + +void DefaultPieceStorage::addUsedPiece(const Piece& piece) { + // TODO ? if nullPiece + usedPieces.push_back(piece); +} + +class FindPiece { +private: + int index; +public: + FindPiece(int index):index(index) {} + + bool operator()(const Piece& piece) { + return piece.getIndex() == index; + } +}; + +Piece DefaultPieceStorage::findUsedPiece(int index) const { + Pieces::const_iterator itr = find_if(usedPieces.begin(), + usedPieces.end(), + FindPiece(index)); + if(itr == usedPieces.end()) { + return Piece::nullPiece; + } else { + return *itr; + } +} + +Piece DefaultPieceStorage::getMissingPiece(const PeerHandle& peer) { + int index = getMissingPieceIndex(peer); + return checkOutPiece(index); +} + +int DefaultPieceStorage::getMissingFastPieceIndex(const PeerHandle& peer) { + int index = -1; + if(peer->isFastExtensionEnabled() && peer->countFastSet() > 0) { + BitfieldMan tempBitfield(bitfieldMan->getBlockLength(), + bitfieldMan->getTotalLength()); + for(Integers::const_iterator itr = peer->getFastSet().begin(); + itr != peer->getFastSet().end(); itr++) { + if(!bitfieldMan->isBitSet(index) && peer->hasPiece(*itr)) { + tempBitfield.setBit(*itr); + } + } + if(isEndGame()) { + index = bitfieldMan->getMissingIndex(tempBitfield.getBitfield(), + tempBitfield.getBitfieldLength()); + } else { + index = bitfieldMan->getMissingUnusedIndex(tempBitfield.getBitfield(), + tempBitfield.getBitfieldLength()); + } + } + return index; +} + +Piece DefaultPieceStorage::getMissingFastPiece(const PeerHandle& peer) { + int index = getMissingFastPieceIndex(peer); + return checkOutPiece(index); +} + +void DefaultPieceStorage::deleteUsedPiece(const Piece& piece) { + if(Piece::isNull(piece)) { + return; + } + Pieces::iterator itr = find(usedPieces.begin(), usedPieces.end(), piece); + if(itr != usedPieces.end()) { + usedPieces.erase(itr); + } +} + +void DefaultPieceStorage::reduceUsedPieces(int delMax) { + int toDelete = usedPieces.size()-delMax; + if(toDelete <= 0) { + return; + } + int fillRate = 10; + while(fillRate < 50) { + int deleted = deleteUsedPiecesByFillRate(fillRate, toDelete); + if(deleted == 0) { + break; + } + toDelete -= deleted; + fillRate += 10; + } +} + +int DefaultPieceStorage::deleteUsedPiecesByFillRate(int fillRate, + int toDelete) { + int deleted = 0; + for(Pieces::iterator itr = usedPieces.begin(); + itr != usedPieces.end() && deleted < toDelete;) { + Piece& piece = *itr; + if(!bitfieldMan->isUseBitSet(piece.getIndex()) && + piece.countCompleteBlock() <= piece.countBlock()*(fillRate/100.0)) { + logger->debug("Deleting used piece index=%d, fillRate(%%)=%d<=%d", + piece.getIndex(), + (piece.countCompleteBlock()*100)/piece.countBlock(), + fillRate); + itr = usedPieces.erase(itr); + deleted++; + } else { + itr++; + } + } + return deleted; +} + +void DefaultPieceStorage::completePiece(const Piece& piece) { + if(Piece::isNull(piece)) { + return; + } + deleteUsedPiece(piece); + if(!isEndGame()) { + reduceUsedPieces(100); + } + if(downloadFinished()) { + return; + } + bitfieldMan->setBit(piece.getIndex()); + bitfieldMan->unsetUseBit(piece.getIndex()); + if(downloadFinished()) { + diskAdaptor->onDownloadComplete(); + if(isSelectiveDownloadingMode()) { + logger->notice(_("Download of selected files was complete.")); + finishSelectiveDownloadingMode(); + } else { + logger->info(_("The download was complete.")); + } + } +} + +bool DefaultPieceStorage::isSelectiveDownloadingMode() { + return bitfieldMan->isFilterEnabled(); +} + +void DefaultPieceStorage::finishSelectiveDownloadingMode() { + bitfieldMan->clearFilter(); + diskAdaptor->addAllDownloadEntry(); +} + +// not unittested +void DefaultPieceStorage::cancelPiece(const Piece& piece) { + if(Piece::isNull(piece)) { + return; + } + updatePiece(piece); + bitfieldMan->unsetUseBit(piece.getIndex()); + if(!isEndGame()) { + if(piece.countCompleteBlock() == 0) { + deleteUsedPiece(piece); + } + } +} + +// not unittested +void DefaultPieceStorage::updatePiece(const Piece& piece) { + if(Piece::isNull(piece)) { + return; + } + Pieces::iterator itr = find(usedPieces.begin(), usedPieces.end(), + piece); + if(itr != usedPieces.end()) { + *itr = piece; + } +} + +// not unittested +void DefaultPieceStorage::syncPiece(Piece& piece) { + if(Piece::isNull(piece)) { + return; + } + Pieces::iterator itr = find(usedPieces.begin(), usedPieces.end(), + piece); + if(itr != usedPieces.end()) { + piece = *itr; + return; + } else { + // hasPiece(piece.getIndex()) is true, then set all bit of + // piece.bitfield to 1 + if(hasPiece(piece.getIndex())) { + piece.setAllBlock(); + } + } +} + +bool DefaultPieceStorage::hasPiece(int index) { + return bitfieldMan->isBitSet(index); +} + +long long int DefaultPieceStorage::getTotalLength() { + return bitfieldMan->getTotalLength(); +} + +long long int DefaultPieceStorage::getFilteredTotalLength() { + return bitfieldMan->getFilteredTotalLength(); +} + +long long int DefaultPieceStorage::getCompletedLength() { + return bitfieldMan->getCompletedLength(); +} + +long long int DefaultPieceStorage::getFilteredCompletedLength() { + return bitfieldMan->getFilteredCompletedLength(); +} + +// not unittested +void DefaultPieceStorage::setFileFilter(const Strings& filePaths) { + if(btContext->getFileMode() != BtContext::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()); + } + FileEntryHandle fileEntry = diskAdaptor->getFileEntryFromPath(*pitr); + bitfieldMan->addFilter(fileEntry->getOffset(), fileEntry->getLength()); + } + bitfieldMan->enableFilter(); +} + +void DefaultPieceStorage::setFileFilter(const Integers& fileIndexes) { + Strings filePaths; + const FileEntries& entries = diskAdaptor->getFileEntries(); + for(int i = 0; i < (int)entries.size(); i++) { + if(find(fileIndexes.begin(), fileIndexes.end(), i+1) != fileIndexes.end()) { + logger->debug("index=%d is %s", i+1, entries.at(i)->getPath().c_str()); + filePaths.push_back(entries.at(i)->getPath()); + } + } + setFileFilter(filePaths); +} + +// not unittested +void DefaultPieceStorage::clearFileFilter() { + bitfieldMan->clearFilter(); + diskAdaptor->addAllDownloadEntry(); +} + +// not unittested +bool DefaultPieceStorage::downloadFinished() { + return bitfieldMan->isAllBitSet(); +} + +// not unittested +void DefaultPieceStorage::initStorage() { + if(diskAdaptor) { + delete diskAdaptor; + diskAdaptor = 0; + } + if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE) { + if(btContext->getFileMode() == BtContext::SINGLE) { + diskAdaptor = new DirectDiskAdaptor(new DefaultDiskWriter(btContext->getTotalLength())); + } else { + diskAdaptor = new MultiDiskAdaptor(new MultiDiskWriter(btContext->getPieceLength())); + } + } else { + diskAdaptor = new CopyDiskAdaptor(new PreAllocationDiskWriter(btContext->getTotalLength())); + ((CopyDiskAdaptor*)diskAdaptor)->setTempFilename(btContext->getName()+".a2tmp"); + } + string storeDir = option->get(PREF_DIR); + if(storeDir == "") { + storeDir = "."; + } + if(btContext->getFileMode() == BtContext::MULTI) { + storeDir += "/"+btContext->getName(); + } + diskAdaptor->setStoreDir(storeDir); + diskAdaptor->setFileEntries(btContext->getFileEntries()); +} + +void DefaultPieceStorage::setBitfield(const unsigned char* bitfield, + int bitfieldLength) { + bitfieldMan->setBitfield(bitfield, bitfieldLength); +} + +int DefaultPieceStorage::getBitfieldLength() { + return bitfieldMan->getBitfieldLength(); +} + +const unsigned char* DefaultPieceStorage::getBitfield() { + return bitfieldMan->getBitfield(); +} + +DiskAdaptor* DefaultPieceStorage::getDiskAdaptor() { + return diskAdaptor; +} + +int DefaultPieceStorage::getPieceLength(int index) { + return bitfieldMan->getBlockLength(index); +} + +void DefaultPieceStorage::advertisePiece(int cuid, int index) { + HaveEntry entry(cuid, index); + haves.push_front(entry); +} + +Integers DefaultPieceStorage::getAdvertisedPieceIndexes(int myCuid, + const Time& lastCheckTime) { + Integers indexes; + for(Haves::const_iterator itr = haves.begin(); itr != haves.end(); itr++) { + const Haves::value_type& have = *itr; + if(have.getCuid() == myCuid) { + continue; + } + if(lastCheckTime.isNewer(have.getRegisteredTime())) { + break; + } + indexes.push_back(have.getIndex()); + } + return indexes; +} + +class FindElapsedHave +{ +private: + int elapsed; +public: + FindElapsedHave(int elapsed):elapsed(elapsed) {} + + bool operator()(const HaveEntry& have) { + if(have.getRegisteredTime().elapsed(elapsed)) { + return true; + } else { + return false; + } + } +}; + +void DefaultPieceStorage::removeAdvertisedPiece(int elapsed) { + Haves::iterator itr = + find_if(haves.begin(), haves.end(), FindElapsedHave(elapsed)); + if(itr != haves.end()) { + logger->debug("Removed %d have entries.", haves.end()-itr); + haves.erase(itr, haves.end()); + } +} diff --git a/src/DefaultPieceStorage.h b/src/DefaultPieceStorage.h new file mode 100644 index 00000000..4b9a2066 --- /dev/null +++ b/src/DefaultPieceStorage.h @@ -0,0 +1,158 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#ifndef _D_DEFAULT_PIECE_STORAGE_H_ +#define _D_DEFAULT_PIECE_STORAGE_H_ + +#include "PieceStorage.h" +#include "BtContext.h" +#include "DiskAdaptor.h" +#include "BitfieldMan.h" +#include "Logger.h" +#include "Option.h" +#include "Piece.h" + +#define END_GAME_PIECE_NUM 20 + +class HaveEntry { +private: + int cuid; + int index; + Time registeredTime; +public: + HaveEntry(int cuid, int index): + cuid(cuid), + index(index) {} + + int getCuid() const { return cuid; } + + int getIndex() const { return index; } + + const Time& getRegisteredTime() const { return registeredTime; } +}; + +typedef deque<HaveEntry> Haves; + +class DefaultPieceStorage : public PieceStorage { +private: + BtContextHandle btContext; + BitfieldMan* bitfieldMan; + DiskAdaptor* diskAdaptor; + Pieces usedPieces; + int endGamePieceNum; + Logger* logger; + const Option* option; + Haves haves; + + int getMissingPieceIndex(const PeerHandle& peer); + int getMissingFastPieceIndex(const PeerHandle& peer); + Piece checkOutPiece(int index); + void addUsedPiece(const Piece& piece); + Piece findUsedPiece(int index) const; + int deleteUsedPiecesByFillRate(int fillRate, int toDelete); + void reduceUsedPieces(int delMax); + void deleteUsedPiece(const Piece& piece); +public: + DefaultPieceStorage(BtContextHandle btContext, const Option* option); + virtual ~DefaultPieceStorage(); + + virtual bool hasMissingPiece(const PeerHandle& peer); + + virtual Piece getMissingPiece(const PeerHandle& peer); + + virtual Piece getMissingFastPiece(const PeerHandle& peer); + + virtual void completePiece(const Piece& piece); + + virtual void cancelPiece(const Piece& piece); + + virtual void updatePiece(const Piece& piece); + + virtual void syncPiece(Piece& piece); + + virtual bool hasPiece(int index); + + virtual long long int getTotalLength(); + + virtual long long int getFilteredTotalLength(); + + virtual long long int getCompletedLength(); + + virtual long long int getFilteredCompletedLength(); + + virtual void initStorage(); + + virtual void setFileFilter(const Strings& filePaths); + + virtual void setFileFilter(const Integers& fileIndexes); + + virtual void clearFileFilter(); + + virtual bool downloadFinished(); + + virtual void setBitfield(const unsigned char* bitfield, + int bitfieldLength); + + virtual int getBitfieldLength(); + + virtual const unsigned char* getBitfield(); + + void setEndGamePieceNum(int num) { + endGamePieceNum = num; + } + + int getEndGamePieceNum() const { + return endGamePieceNum; + } + + virtual bool isSelectiveDownloadingMode(); + + virtual void finishSelectiveDownloadingMode(); + + virtual bool isEndGame(); + + virtual DiskAdaptor* getDiskAdaptor(); + + virtual int getPieceLength(int index); + + virtual void advertisePiece(int cuid, int index); + + virtual Integers getAdvertisedPieceIndexes(int myCuid, + const Time& lastCheckTime); + + virtual void removeAdvertisedPiece(int elapsed); + +}; + +#endif // _D_DEFAULT_PIECE_STORAGE_H_ diff --git a/src/DelegatingPeerListProcessor.cc b/src/DelegatingPeerListProcessor.cc index b91554bb..38f9395c 100644 --- a/src/DelegatingPeerListProcessor.cc +++ b/src/DelegatingPeerListProcessor.cc @@ -54,4 +54,5 @@ bool DelegatingPeerListProcessor::canHandle(const MetaEntry* peersEntry) const { return true; } } + return false; } diff --git a/src/DirectDiskAdaptor.cc b/src/DirectDiskAdaptor.cc index f360393c..290516e7 100644 --- a/src/DirectDiskAdaptor.cc +++ b/src/DirectDiskAdaptor.cc @@ -39,7 +39,7 @@ DirectDiskAdaptor::DirectDiskAdaptor(DiskWriter* diskWriter):DiskAdaptor(diskWri DirectDiskAdaptor::~DirectDiskAdaptor() {} string DirectDiskAdaptor::getFilePath() const { - return storeDir+"/"+fileEntries.front().path; + return storeDir+"/"+fileEntries.front()->getPath(); } void DirectDiskAdaptor::onDownloadComplete() { diff --git a/src/Directory.cc b/src/Directory.cc index f3e2f2b3..c342f94b 100644 --- a/src/Directory.cc +++ b/src/Directory.cc @@ -42,6 +42,8 @@ Directory::Directory(const string& name):name(name) {} +Directory::Directory() {} + Directory::~Directory() { for(Files::iterator itr = files.begin(); itr != files.end(); itr++) { delete *itr; @@ -49,6 +51,9 @@ Directory::~Directory() { } void Directory::createDir(const string& parentDir, bool recursive) const { + if(name.size() == 0) { + return; + } string path = parentDir+"/"+name; File f(path); if(f.exists()) { diff --git a/src/Directory.h b/src/Directory.h index 1eef65fb..e3fb8cd9 100644 --- a/src/Directory.h +++ b/src/Directory.h @@ -48,10 +48,13 @@ private: Files files; public: Directory(const string& name); + Directory(); ~Directory(); void createDir(const string& parentDir, bool recursive) const; void addFile(Directory* directory); }; +typedef SharedHandle<Directory> DirectoryHandle; + #endif // _D_DIRECTORY_H_ diff --git a/src/DiskAdaptor.cc b/src/DiskAdaptor.cc index 2ed4d2c2..9044b31b 100644 --- a/src/DiskAdaptor.cc +++ b/src/DiskAdaptor.cc @@ -36,15 +36,12 @@ #include "DlAbortEx.h" #include "LogFactory.h" -DiskAdaptor::DiskAdaptor(DiskWriter* diskWriter):diskWriter(diskWriter), topDir(NULL) { +DiskAdaptor::DiskAdaptor(DiskWriter* diskWriter):diskWriter(diskWriter) { logger = LogFactory::getInstance(); } DiskAdaptor::~DiskAdaptor() { delete diskWriter; - if(topDir != NULL) { - delete topDir; - } } void DiskAdaptor::openFile() { @@ -75,10 +72,10 @@ string DiskAdaptor::sha1Sum(long long int offset, long long int length) { return diskWriter->sha1Sum(offset, length); } -FileEntry DiskAdaptor::getFileEntryFromPath(const string& fileEntryPath) const { +FileEntryHandle DiskAdaptor::getFileEntryFromPath(const string& fileEntryPath) const { for(FileEntries::const_iterator itr = fileEntries.begin(); itr != fileEntries.end(); itr++) { - if(itr->path == fileEntryPath) { + if((*itr)->getPath() == fileEntryPath) { return *itr; } } @@ -88,8 +85,8 @@ FileEntry DiskAdaptor::getFileEntryFromPath(const string& fileEntryPath) const { bool DiskAdaptor::addDownloadEntry(const string& fileEntryPath) { for(FileEntries::iterator itr = fileEntries.begin(); itr != fileEntries.end(); itr++) { - if(itr->path == fileEntryPath) { - itr->requested = true; + if((*itr)->getPath() == fileEntryPath) { + (*itr)->setRequested(true); return true; } } @@ -100,20 +97,20 @@ bool DiskAdaptor::addDownloadEntry(int index) { if(fileEntries.size() <= (unsigned int)index) { return false; } - fileEntries.at(index).requested = true; + fileEntries.at(index)->setRequested(true); return true; } void DiskAdaptor::addAllDownloadEntry() { for(FileEntries::iterator itr = fileEntries.begin(); itr != fileEntries.end(); itr++) { - itr->requested = true; + (*itr)->setRequested(true); } } void DiskAdaptor::removeAllDownloadEntry() { for(FileEntries::iterator itr = fileEntries.begin(); itr != fileEntries.end(); itr++) { - itr->requested = false; + (*itr)->setRequested(false); } } diff --git a/src/DiskAdaptor.h b/src/DiskAdaptor.h index 276def84..a172cd4f 100644 --- a/src/DiskAdaptor.h +++ b/src/DiskAdaptor.h @@ -40,13 +40,13 @@ #include "Directory.h" #include "DiskWriter.h" #include "Logger.h" +#include "FileEntry.h" class DiskAdaptor { protected: DiskWriter* diskWriter; string storeDir; FileEntries fileEntries; - const Directory* topDir; const Logger* logger; virtual string getFilePath() const = 0; public: @@ -66,7 +66,9 @@ public: void setFileEntries(const FileEntries& fileEntries) { this->fileEntries = fileEntries; } - FileEntry getFileEntryFromPath(const string& fileEntryPath) const; + + FileEntryHandle getFileEntryFromPath(const string& fileEntryPath) const; + const FileEntries& getFileEntries() const { return fileEntries; } bool addDownloadEntry(const string& fileEntryPath); @@ -75,15 +77,8 @@ public: void removeAllDownloadEntry(); void setStoreDir(const string& storeDir) { this->storeDir = storeDir; } - string getStoreDir() const { return this->storeDir; } - void setTopDir(const Directory* dirctory) { - if(this->topDir != NULL) { - delete topDir; - } - this->topDir = dirctory; - } - const Directory* getTopDir() const { return this->topDir; } + string getStoreDir() const { return this->storeDir; } }; #endif // _D_DISK_ADAPTOR_H_ diff --git a/src/DownloadEngineFactory.cc b/src/DownloadEngineFactory.cc index 6ac1d745..2bb84da2 100644 --- a/src/DownloadEngineFactory.cc +++ b/src/DownloadEngineFactory.cc @@ -49,6 +49,10 @@ # include "UnionSeedCriteria.h" # include "TimeSeedCriteria.h" # include "ShareRatioSeedCriteria.h" +# include "DefaultPieceStorage.h" +# include "DefaultPeerStorage.h" +# include "DefaultBtAnnounce.h" +# include "DefaultBtProgressInfoFile.h" #endif // ENABLE_BITTORRENT ConsoleDownloadEngine* @@ -76,8 +80,8 @@ DownloadEngineFactory::newConsoleEngine(const Option* op, #ifdef ENABLE_BITTORRENT TorrentConsoleDownloadEngine* -DownloadEngineFactory::newTorrentConsoleEngine(const Option* op, - const string& torrentFile, +DownloadEngineFactory::newTorrentConsoleEngine(const BtContextHandle& btContext, + const Option* op, const Strings& targetFiles) { TorrentConsoleDownloadEngine* te = new TorrentConsoleDownloadEngine(); @@ -86,19 +90,44 @@ DownloadEngineFactory::newTorrentConsoleEngine(const Option* op, te->segmentMan = new SegmentMan(); te->segmentMan->diskWriter = byteArrayDiskWriter; te->segmentMan->option = op; - te->torrentMan = new TorrentMan(); - te->torrentMan->setStoreDir(op->get(PREF_DIR)); - te->torrentMan->option = op; + BtRuntimeHandle btRuntime(new BtRuntime()); + BtRegistry::registerBtRuntime(btContext->getInfoHashAsString(), btRuntime); + + PieceStorageHandle pieceStorage(new DefaultPieceStorage(btContext, op)); + BtRegistry::registerPieceStorage(btContext->getInfoHashAsString(), pieceStorage); + + PeerStorageHandle peerStorage(new DefaultPeerStorage(btContext, op)); + BtRegistry::registerPeerStorage(btContext->getInfoHashAsString(), peerStorage); + + BtAnnounceHandle btAnnounce(new DefaultBtAnnounce(btContext, op)); + BtRegistry::registerBtAnnounce(btContext->getInfoHashAsString(), btAnnounce); + btAnnounce->shuffleAnnounce(); + + BtProgressInfoFileHandle btProgressInfoFile(new DefaultBtProgressInfoFile(btContext, op)); + BtRegistry::registerBtProgressInfoFile(btContext->getInfoHashAsString(), + btProgressInfoFile); + + te->setBtContext(btContext); + // initialize file storage + pieceStorage->initStorage(); + if(btProgressInfoFile->exists()) { + // load .aria2 file if it exists. + btProgressInfoFile->load(); + pieceStorage->getDiskAdaptor()->openExistingFile(); + } else { + pieceStorage->getDiskAdaptor()->initAndOpenFile(); + } + Integers selectIndexes; Util::unfoldRange(op->get(PREF_SELECT_FILE), selectIndexes); if(selectIndexes.size()) { - te->torrentMan->setup(torrentFile, selectIndexes); + pieceStorage->setFileFilter(selectIndexes); } else { - te->torrentMan->setup(torrentFile, targetFiles); + pieceStorage->setFileFilter(targetFiles); } PeerListenCommand* listenCommand = - new PeerListenCommand(te->torrentMan->getNewCuid(), te); + new PeerListenCommand(btRuntime->getNewCuid(), te, btContext); int port; int listenPort = op->getAsInt(PREF_LISTEN_PORT); if(listenPort == -1) { @@ -110,31 +139,39 @@ DownloadEngineFactory::newTorrentConsoleEngine(const Option* op, printf(_("Errors occurred while binding port.\n")); exit(EXIT_FAILURE); } - te->torrentMan->setPort(port); + btRuntime->setListenPort(port); te->commands.push_back(listenCommand); - te->commands.push_back(new TrackerWatcherCommand(te->torrentMan->getNewCuid(), - te)); - te->commands.push_back(new TrackerUpdateCommand(te->torrentMan->getNewCuid(), - te)); - te->commands.push_back(new TorrentAutoSaveCommand(te->torrentMan->getNewCuid(), + te->commands.push_back(new TrackerWatcherCommand(btRuntime->getNewCuid(), + te, + btContext)); + te->commands.push_back(new TrackerUpdateCommand(btRuntime->getNewCuid(), + te, + btContext)); + te->commands.push_back(new TorrentAutoSaveCommand(btRuntime->getNewCuid(), te, + btContext, op->getAsInt(PREF_AUTO_SAVE_INTERVAL))); - te->commands.push_back(new PeerChokeCommand(te->torrentMan->getNewCuid(), - te, 10)); - te->commands.push_back(new HaveEraseCommand(te->torrentMan->getNewCuid(), - te, 10)); + te->commands.push_back(new PeerChokeCommand(btRuntime->getNewCuid(), + te, + btContext, + 10)); + te->commands.push_back(new HaveEraseCommand(btRuntime->getNewCuid(), + te, + btContext, + 10)); SharedHandle<UnionSeedCriteria> unionCri = new UnionSeedCriteria(); if(op->defined(PREF_SEED_TIME)) { unionCri->addSeedCriteria(new TimeSeedCriteria(op->getAsInt(PREF_SEED_TIME)*60)); } if(op->defined(PREF_SEED_RATIO)) { - unionCri->addSeedCriteria(new ShareRatioSeedCriteria(op->getAsDouble(PREF_SEED_RATIO), te->torrentMan)); + unionCri->addSeedCriteria(new ShareRatioSeedCriteria(op->getAsDouble(PREF_SEED_RATIO), btContext)); } if(unionCri->getSeedCriterion().size() > 0) { - te->commands.push_back(new SeedCheckCommand(te->torrentMan->getNewCuid(), + te->commands.push_back(new SeedCheckCommand(btRuntime->getNewCuid(), te, + btContext, unionCri)); } return te; diff --git a/src/DownloadEngineFactory.h b/src/DownloadEngineFactory.h index 33ee1299..f5f801c3 100644 --- a/src/DownloadEngineFactory.h +++ b/src/DownloadEngineFactory.h @@ -50,8 +50,8 @@ public: #ifdef ENABLE_BITTORRENT static TorrentConsoleDownloadEngine* - newTorrentConsoleEngine(const Option* option, - const string& torrentFile, + newTorrentConsoleEngine(const BtContextHandle& btContext, + const Option* option, const Strings& targetFiles); #endif // ENABLE_BITTORRENT }; diff --git a/src/File.cc b/src/File.cc index 459f6b53..0cd732b8 100644 --- a/src/File.cc +++ b/src/File.cc @@ -33,6 +33,7 @@ */ /* copyright --> */ #include "File.h" +#include "Util.h" #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> @@ -83,3 +84,30 @@ long long int File::size() { } return fstat.st_size; } + +bool File::mkdirs() { + if(isDir()) { + return false; + } + Strings dirs; + Util::slice(dirs, name, '/'); + if(!dirs.size()) { + return true; + } + string accDir; + if(Util::startsWith(name, "/")) { + accDir = "/"; + } + mode_t mode = S_IRUSR|S_IWUSR|S_IXUSR; + for(Strings::const_iterator itr = dirs.begin(); itr != dirs.end(); + itr++, accDir += "/") { + accDir += *itr; + if(File(accDir).isDir()) { + continue; + } + if(mkdir(accDir.c_str(), mode) == -1) { + return false; + } + } + return true; +} @@ -72,6 +72,15 @@ public: */ bool remove(); + /** + * Creates the directory denoted by name. + * This method creates complete directory structure. + * Returns true if the directory is created successfully, otherwise returns + * false. + * If the directory already exists, then returns false. + */ + bool mkdirs(); + long long int size(); }; diff --git a/src/FileEntry.cc b/src/FileEntry.cc new file mode 100644 index 00000000..1e74ffa8 --- /dev/null +++ b/src/FileEntry.cc @@ -0,0 +1,64 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#include "FileEntry.h" +#include "File.h" +#include "DlAbortEx.h" +#include <libgen.h> + +FileEntry::FileEntry(const string& path, + long long int length, + long long int offset): + path(path), length(length), offset(offset), + extracted(false), requested(true) {} + +FileEntry::~FileEntry() {} + +void FileEntry::setupDir(const string& parentDir) { + string absPath = parentDir+"/"+path; + char* temp = strdup(absPath.c_str()); + string dir = string(dirname(temp)); + free(temp); + if(!dir.size()) { + return; + } + File f(dir); + if(f.isDir()) { + // nothing to do + } else if(f.exists()) { + throw new DlAbortEx("%s is not a directory.", dir.c_str()); + } else if(!f.mkdirs()) { + throw new DlAbortEx("Failed to create directory %s.", dir.c_str()); + } +} diff --git a/src/FileEntry.h b/src/FileEntry.h index 5c7281d0..0113921a 100644 --- a/src/FileEntry.h +++ b/src/FileEntry.h @@ -38,18 +38,41 @@ #include "common.h" class FileEntry { -public: +private: string path; long long int length; long long int offset; bool extracted; bool requested; - FileEntry(const string& path, long long int length, long long int offset): - path(path), length(length), offset(offset), - extracted(false), requested(true) {} - ~FileEntry() {} +public: + FileEntry(const string& path, long long int length, long long int offset); + + ~FileEntry(); + + const string& getPath() const { return path; } + + void setPath(const string& path) { this->path = path; } + + long long int getLength() const { return length; } + + void setLength(long long int length) { this->length = length; } + + long long int getOffset() const { return offset; } + + void setOffset(long long int offset) { this->offset = offset; } + + bool isExtracted() const { return extracted; } + + void setExtracted(bool flag) { this->extracted = flag; } + + bool isRequested() const { return requested; } + + void setRequested(bool flag) { this->requested = flag; } + + void setupDir(const string& parentDir); }; -typedef deque<FileEntry> FileEntries; +typedef SharedHandle<FileEntry> FileEntryHandle; +typedef deque<FileEntryHandle> FileEntries; #endif // _D_FILE_ENTRY_H_ diff --git a/src/HandshakeMessage.cc b/src/HandshakeMessage.cc index a3af8579..9e9fd390 100644 --- a/src/HandshakeMessage.cc +++ b/src/HandshakeMessage.cc @@ -93,7 +93,7 @@ string HandshakeMessage::toString() const { void HandshakeMessage::check() const { PeerMessageUtil::checkHandshake(this, - peerInteraction->getTorrentMan()->getInfoHash()); + peerInteraction->getBtContext()->getInfoHash()); } bool HandshakeMessage::isFastExtensionSupported() const { diff --git a/src/HandshakeMessage.h b/src/HandshakeMessage.h index bd2ff0ae..6c931c91 100644 --- a/src/HandshakeMessage.h +++ b/src/HandshakeMessage.h @@ -36,7 +36,6 @@ #define _D_HANDSHAKE_MESSAGE_H_ #include "SimplePeerMessage.h" -#include "TorrentMan.h" #define PSTR "BitTorrent protocol" #define HANDSHAKE_MESSAGE_LENGTH 68 diff --git a/src/HaveEraseCommand.cc b/src/HaveEraseCommand.cc index d0fb3b2d..0758d10a 100644 --- a/src/HaveEraseCommand.cc +++ b/src/HaveEraseCommand.cc @@ -34,13 +34,21 @@ /* copyright --> */ #include "HaveEraseCommand.h" +HaveEraseCommand::HaveEraseCommand(int cuid, + TorrentDownloadEngine* e, + const BtContextHandle& btContext, + int interval) + :BtContextAwareCommand(cuid, btContext), + e(e), + interval(interval) {} + bool HaveEraseCommand::execute() { - if(e->torrentMan->isHalt()) { + if(btRuntime->isHalt()) { return true; } if(cp.elapsed(interval)) { cp.reset(); - e->torrentMan->removeAdvertisedPiece(5); + pieceStorage->removeAdvertisedPiece(5); } e->commands.push_back(this); return false; diff --git a/src/HaveEraseCommand.h b/src/HaveEraseCommand.h index 7730111f..59a663bf 100644 --- a/src/HaveEraseCommand.h +++ b/src/HaveEraseCommand.h @@ -35,19 +35,19 @@ #ifndef _D_HAVE_ERASE_COMMAND_H_ #define _D_HAVE_ERASE_COMMAND_H_ -#include "Command.h" +#include "BtContextAwareCommand.h" #include "TorrentDownloadEngine.h" -class HaveEraseCommand : public Command { +class HaveEraseCommand : public BtContextAwareCommand { private: TorrentDownloadEngine* e; Time cp; int interval; public: - HaveEraseCommand(int cuid, TorrentDownloadEngine* e, int interval) - :Command(cuid), - e(e), - interval(interval) {} + HaveEraseCommand(int cuid, + TorrentDownloadEngine* e, + const BtContextHandle& btContext, + int interval); virtual ~HaveEraseCommand() {} diff --git a/src/Makefile.am b/src/Makefile.am index 3807881e..e7860354 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -69,7 +69,6 @@ SRCS += MetaEntry.h\ MetaFileUtil.cc MetaFileUtil.h\ MetaEntryVisitor.h\ ShaVisitor.cc ShaVisitor.h\ - TorrentMan.cc TorrentMan.h\ PeerConnection.cc PeerConnection.h\ PeerMessageUtil.cc PeerMessageUtil.h\ PeerAbstractCommand.cc PeerAbstractCommand.h\ @@ -92,7 +91,7 @@ SRCS += MetaEntry.h\ CopyDiskAdaptor.cc CopyDiskAdaptor.h\ DirectDiskAdaptor.cc DirectDiskAdaptor.h\ MultiDiskAdaptor.cc MultiDiskAdaptor.h\ - FileEntry.h\ + FileEntry.cc FileEntry.h\ TrackerUpdateCommand.cc TrackerUpdateCommand.h\ ByteArrayDiskWriter.cc ByteArrayDiskWriter.h\ PeerChokeCommand.cc PeerChokeCommand.h\ @@ -125,7 +124,21 @@ SRCS += MetaEntry.h\ DefaultPeerListProcessor.cc DefaultPeerListProcessor.h\ CompactPeerListProcessor.cc CompactPeerListProcessor.h\ DelegatingPeerListProcessor.cc DelegatingPeerListProcessor.h\ - AnnounceList.h AnnounceList.cc + AnnounceTier.h\ + AnnounceList.h AnnounceList.cc\ + BtContext.h\ + DefaultBtContext.cc DefaultBtContext.h\ + PieceStorage.h\ + DefaultPieceStorage.cc DefaultPieceStorage.h\ + PeerService.h\ + DefaultPeerStorage.cc DefaultPeerStorage.h\ + BtAnnounce.h\ + DefaultBtAnnounce.cc DefaultBtAnnounce.h\ + BtRegistry.cc BtRegistry.h\ + BtRuntime.h\ + BtProgressInfoFile.h\ + DefaultBtProgressInfoFile.cc DefaultBtProgressInfoFile.h\ + BtContextAwareCommand.cc BtContextAwareCommand.h endif # ENABLE_BITTORRENT if ENABLE_METALINK diff --git a/src/Makefile.in b/src/Makefile.in index f52fe022..3ebd9e44 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -46,7 +46,6 @@ bin_PROGRAMS = aria2c$(EXEEXT) @ENABLE_BITTORRENT_TRUE@ MetaFileUtil.cc MetaFileUtil.h\ @ENABLE_BITTORRENT_TRUE@ MetaEntryVisitor.h\ @ENABLE_BITTORRENT_TRUE@ ShaVisitor.cc ShaVisitor.h\ -@ENABLE_BITTORRENT_TRUE@ TorrentMan.cc TorrentMan.h\ @ENABLE_BITTORRENT_TRUE@ PeerConnection.cc PeerConnection.h\ @ENABLE_BITTORRENT_TRUE@ PeerMessageUtil.cc PeerMessageUtil.h\ @ENABLE_BITTORRENT_TRUE@ PeerAbstractCommand.cc PeerAbstractCommand.h\ @@ -69,7 +68,7 @@ bin_PROGRAMS = aria2c$(EXEEXT) @ENABLE_BITTORRENT_TRUE@ CopyDiskAdaptor.cc CopyDiskAdaptor.h\ @ENABLE_BITTORRENT_TRUE@ DirectDiskAdaptor.cc DirectDiskAdaptor.h\ @ENABLE_BITTORRENT_TRUE@ MultiDiskAdaptor.cc MultiDiskAdaptor.h\ -@ENABLE_BITTORRENT_TRUE@ FileEntry.h\ +@ENABLE_BITTORRENT_TRUE@ FileEntry.cc FileEntry.h\ @ENABLE_BITTORRENT_TRUE@ TrackerUpdateCommand.cc TrackerUpdateCommand.h\ @ENABLE_BITTORRENT_TRUE@ ByteArrayDiskWriter.cc ByteArrayDiskWriter.h\ @ENABLE_BITTORRENT_TRUE@ PeerChokeCommand.cc PeerChokeCommand.h\ @@ -102,7 +101,21 @@ bin_PROGRAMS = aria2c$(EXEEXT) @ENABLE_BITTORRENT_TRUE@ DefaultPeerListProcessor.cc DefaultPeerListProcessor.h\ @ENABLE_BITTORRENT_TRUE@ CompactPeerListProcessor.cc CompactPeerListProcessor.h\ @ENABLE_BITTORRENT_TRUE@ DelegatingPeerListProcessor.cc DelegatingPeerListProcessor.h\ -@ENABLE_BITTORRENT_TRUE@ AnnounceList.h AnnounceList.cc +@ENABLE_BITTORRENT_TRUE@ AnnounceTier.h\ +@ENABLE_BITTORRENT_TRUE@ AnnounceList.h AnnounceList.cc\ +@ENABLE_BITTORRENT_TRUE@ BtContext.h\ +@ENABLE_BITTORRENT_TRUE@ DefaultBtContext.cc DefaultBtContext.h\ +@ENABLE_BITTORRENT_TRUE@ PieceStorage.h\ +@ENABLE_BITTORRENT_TRUE@ DefaultPieceStorage.cc DefaultPieceStorage.h\ +@ENABLE_BITTORRENT_TRUE@ PeerService.h\ +@ENABLE_BITTORRENT_TRUE@ DefaultPeerStorage.cc DefaultPeerStorage.h\ +@ENABLE_BITTORRENT_TRUE@ BtAnnounce.h\ +@ENABLE_BITTORRENT_TRUE@ DefaultBtAnnounce.cc DefaultBtAnnounce.h\ +@ENABLE_BITTORRENT_TRUE@ BtRegistry.cc BtRegistry.h\ +@ENABLE_BITTORRENT_TRUE@ BtRuntime.h\ +@ENABLE_BITTORRENT_TRUE@ BtProgressInfoFile.h\ +@ENABLE_BITTORRENT_TRUE@ DefaultBtProgressInfoFile.cc DefaultBtProgressInfoFile.h\ +@ENABLE_BITTORRENT_TRUE@ BtContextAwareCommand.cc BtContextAwareCommand.h @ENABLE_METALINK_TRUE@am__append_3 = Metalinker.cc Metalinker.h\ @ENABLE_METALINK_TRUE@ MetalinkEntry.cc MetalinkEntry.h\ @@ -172,10 +185,9 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ BitfieldMan.cc BitfieldMan.h NameResolver.cc NameResolver.h \ MetaEntry.h Data.cc Data.h Dictionary.cc Dictionary.h List.cc \ List.h MetaFileUtil.cc MetaFileUtil.h MetaEntryVisitor.h \ - ShaVisitor.cc ShaVisitor.h TorrentMan.cc TorrentMan.h \ - PeerConnection.cc PeerConnection.h PeerMessageUtil.cc \ - PeerMessageUtil.h PeerAbstractCommand.cc PeerAbstractCommand.h \ - PeerInitiateConnectionCommand.cc \ + ShaVisitor.cc ShaVisitor.h PeerConnection.cc PeerConnection.h \ + PeerMessageUtil.cc PeerMessageUtil.h PeerAbstractCommand.cc \ + PeerAbstractCommand.h PeerInitiateConnectionCommand.cc \ PeerInitiateConnectionCommand.h PeerInteractionCommand.cc \ PeerInteractionCommand.h Peer.cc Peer.h \ TorrentDownloadEngine.cc TorrentDownloadEngine.h \ @@ -189,11 +201,11 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ MultiDiskWriter.h DiskAdaptor.cc DiskAdaptor.h \ CopyDiskAdaptor.cc CopyDiskAdaptor.h DirectDiskAdaptor.cc \ DirectDiskAdaptor.h MultiDiskAdaptor.cc MultiDiskAdaptor.h \ - FileEntry.h TrackerUpdateCommand.cc TrackerUpdateCommand.h \ - ByteArrayDiskWriter.cc ByteArrayDiskWriter.h \ - PeerChokeCommand.cc PeerChokeCommand.h ChokeMessage.cc \ - ChokeMessage.h UnchokeMessage.cc UnchokeMessage.h \ - InterestedMessage.cc InterestedMessage.h \ + FileEntry.cc FileEntry.h TrackerUpdateCommand.cc \ + TrackerUpdateCommand.h ByteArrayDiskWriter.cc \ + ByteArrayDiskWriter.h PeerChokeCommand.cc PeerChokeCommand.h \ + ChokeMessage.cc ChokeMessage.h UnchokeMessage.cc \ + UnchokeMessage.h InterestedMessage.cc InterestedMessage.h \ NotInterestedMessage.cc NotInterestedMessage.h HaveMessage.cc \ HaveMessage.h BitfieldMessage.cc BitfieldMessage.h \ RequestMessage.cc RequestMessage.h PieceMessage.cc \ @@ -211,9 +223,17 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ PeerListProcessor.h DefaultPeerListProcessor.cc \ DefaultPeerListProcessor.h CompactPeerListProcessor.cc \ CompactPeerListProcessor.h DelegatingPeerListProcessor.cc \ - DelegatingPeerListProcessor.h AnnounceList.h AnnounceList.cc \ - Metalinker.cc Metalinker.h MetalinkEntry.cc MetalinkEntry.h \ - MetalinkResource.cc MetalinkResource.h MetalinkProcessor.h \ + DelegatingPeerListProcessor.h AnnounceTier.h AnnounceList.h \ + AnnounceList.cc BtContext.h DefaultBtContext.cc \ + DefaultBtContext.h PieceStorage.h DefaultPieceStorage.cc \ + DefaultPieceStorage.h PeerService.h DefaultPeerStorage.cc \ + DefaultPeerStorage.h BtAnnounce.h DefaultBtAnnounce.cc \ + DefaultBtAnnounce.h BtRegistry.cc BtRegistry.h BtRuntime.h \ + BtProgressInfoFile.h DefaultBtProgressInfoFile.cc \ + DefaultBtProgressInfoFile.h BtContextAwareCommand.cc \ + BtContextAwareCommand.h Metalinker.cc Metalinker.h \ + MetalinkEntry.cc MetalinkEntry.h MetalinkResource.cc \ + MetalinkResource.h MetalinkProcessor.h \ Xml2MetalinkProcessor.cc Xml2MetalinkProcessor.h \ MetalinkRequestInfo.cc MetalinkRequestInfo.h @ENABLE_ASYNC_DNS_TRUE@am__objects_1 = NameResolver.$(OBJEXT) @@ -221,7 +241,6 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ @ENABLE_BITTORRENT_TRUE@ Dictionary.$(OBJEXT) List.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ MetaFileUtil.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ ShaVisitor.$(OBJEXT) \ -@ENABLE_BITTORRENT_TRUE@ TorrentMan.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ PeerConnection.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ PeerMessageUtil.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ PeerAbstractCommand.$(OBJEXT) \ @@ -243,6 +262,7 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ @ENABLE_BITTORRENT_TRUE@ CopyDiskAdaptor.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ DirectDiskAdaptor.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ MultiDiskAdaptor.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ FileEntry.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ TrackerUpdateCommand.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ ByteArrayDiskWriter.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ PeerChokeCommand.$(OBJEXT) \ @@ -270,7 +290,14 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ @ENABLE_BITTORRENT_TRUE@ DefaultPeerListProcessor.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ CompactPeerListProcessor.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ DelegatingPeerListProcessor.$(OBJEXT) \ -@ENABLE_BITTORRENT_TRUE@ AnnounceList.$(OBJEXT) +@ENABLE_BITTORRENT_TRUE@ AnnounceList.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ DefaultBtContext.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ DefaultPieceStorage.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ DefaultPeerStorage.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ DefaultBtAnnounce.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ BtRegistry.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ DefaultBtProgressInfoFile.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ BtContextAwareCommand.$(OBJEXT) @ENABLE_METALINK_TRUE@am__objects_3 = Metalinker.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkEntry.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkResource.$(OBJEXT) \ @@ -598,6 +625,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Base64.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BitfieldMan.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BitfieldMessage.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtContextAwareCommand.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtRegistry.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ByteArrayDiskWriter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CancelMessage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChokeMessage.Po@am__quote@ @@ -608,8 +637,13 @@ distclean-compile: @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)/DefaultBtAnnounce.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtContext.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtProgressInfoFile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultDiskWriter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultPeerListProcessor.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultPeerStorage.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultPieceStorage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DelegatingPeerListProcessor.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@ @@ -620,6 +654,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadEngineFactory.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FeatureConfig.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/File.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileEntry.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpConnection.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpDownloadCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpInitiateConnectionCommand.Po@am__quote@ @@ -687,7 +722,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentAutoSaveCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentConsoleDownloadEngine.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentDownloadEngine.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentMan.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentRequestInfo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TrackerUpdateCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TrackerWatcherCommand.Po@am__quote@ diff --git a/src/MultiDiskAdaptor.cc b/src/MultiDiskAdaptor.cc index 835a11f3..fc4a5400 100644 --- a/src/MultiDiskAdaptor.cc +++ b/src/MultiDiskAdaptor.cc @@ -46,14 +46,21 @@ string MultiDiskAdaptor::getFilePath() const { return storeDir; } +void MultiDiskAdaptor::mkdir() const { + for(FileEntries::const_iterator itr = fileEntries.begin(); + itr != fileEntries.end(); itr++) { + (*itr)->setupDir(storeDir); + } +} + void MultiDiskAdaptor::openFile() { - topDir->createDir(storeDir, true); + mkdir(); setDiskWriterFileEntries(); DiskAdaptor::openFile(); } void MultiDiskAdaptor::initAndOpenFile() { - topDir->createDir(storeDir, true); + mkdir(); setDiskWriterFileEntries(); DiskAdaptor::initAndOpenFile(); } diff --git a/src/MultiDiskAdaptor.h b/src/MultiDiskAdaptor.h index 0012779a..27fa74ee 100644 --- a/src/MultiDiskAdaptor.h +++ b/src/MultiDiskAdaptor.h @@ -41,6 +41,7 @@ class MultiDiskAdaptor : public DiskAdaptor { private: void setDiskWriterFileEntries(); + void mkdir() const; protected: virtual string getFilePath() const; public: diff --git a/src/MultiDiskWriter.cc b/src/MultiDiskWriter.cc index f49db771..b231d564 100644 --- a/src/MultiDiskWriter.cc +++ b/src/MultiDiskWriter.cc @@ -68,7 +68,7 @@ void MultiDiskWriter::setFileEntries(const FileEntries& fileEntries) { void MultiDiskWriter::openFile(const string& filename) { for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); itr != diskWriterEntries.end(); itr++) { - (*itr)->diskWriter->openFile(filename+"/"+(*itr)->fileEntry.path); + (*itr)->diskWriter->openFile(filename+"/"+(*itr)->fileEntry->getPath()); } } @@ -76,7 +76,7 @@ void MultiDiskWriter::openFile(const string& filename) { void MultiDiskWriter::initAndOpenFile(const string& filename) { for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); itr != diskWriterEntries.end(); itr++) { - (*itr)->diskWriter->initAndOpenFile(filename+"/"+(*itr)->fileEntry.path); + (*itr)->diskWriter->initAndOpenFile(filename+"/"+(*itr)->fileEntry->getPath()); } } @@ -90,7 +90,7 @@ void MultiDiskWriter::closeFile() { void MultiDiskWriter::openExistingFile(const string& filename) { for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); itr != diskWriterEntries.end(); itr++) { - (*itr)->diskWriter->openExistingFile(filename+"/"+(*itr)->fileEntry.path); + (*itr)->diskWriter->openExistingFile(filename+"/"+(*itr)->fileEntry->getPath()); } } @@ -107,7 +107,7 @@ void MultiDiskWriter::writeData(const char* data, int len, long long int offset) writing = true; fileOffset = 0; } else { - fileOffset -= (*itr)->fileEntry.length; + fileOffset -= (*itr)->fileEntry->getLength(); } } if(!writing) { @@ -116,14 +116,14 @@ void MultiDiskWriter::writeData(const char* data, int len, long long int offset) } bool MultiDiskWriter::isInRange(const DiskWriterEntry* entry, long long int offset) const { - return entry->fileEntry.offset <= offset && - offset < entry->fileEntry.offset+entry->fileEntry.length; + return entry->fileEntry->getOffset() <= offset && + offset < entry->fileEntry->getOffset()+entry->fileEntry->getLength(); } int MultiDiskWriter::calculateLength(const DiskWriterEntry* entry, long long int fileOffset, int rem) const { int length; - if(entry->fileEntry.length < fileOffset+rem) { - length = entry->fileEntry.length-fileOffset; + if(entry->fileEntry->getLength() < fileOffset+rem) { + length = entry->fileEntry->getLength()-fileOffset; } else { length = rem; } @@ -144,7 +144,7 @@ int MultiDiskWriter::readData(char* data, int len, long long int offset) { reading = true; fileOffset = 0; } else { - fileOffset -= (*itr)->fileEntry.length; + fileOffset -= (*itr)->fileEntry->getLength(); } } if(!reading) { @@ -187,7 +187,7 @@ string MultiDiskWriter::sha1Sum(long long int offset, long long int length) { reading = true; fileOffset = 0; } else { - fileOffset -= (*itr)->fileEntry.length; + fileOffset -= (*itr)->fileEntry->getLength(); } } if(!reading) { diff --git a/src/MultiDiskWriter.h b/src/MultiDiskWriter.h index d0ac9655..c7e5d26c 100644 --- a/src/MultiDiskWriter.h +++ b/src/MultiDiskWriter.h @@ -36,16 +36,16 @@ #define _D_MULTI_DISK_WRITER_H_ #include "DefaultDiskWriter.h" -#include "TorrentMan.h" #include "messageDigest.h" +#include "FileEntry.h" class DiskWriterEntry { public: - FileEntry fileEntry; + FileEntryHandle fileEntry; DiskWriter* diskWriter; public: - DiskWriterEntry(const FileEntry& fileEntry):fileEntry(fileEntry) { - diskWriter = new DefaultDiskWriter(this->fileEntry.length); + DiskWriterEntry(const FileEntryHandle& fileEntry):fileEntry(fileEntry) { + diskWriter = new DefaultDiskWriter(this->fileEntry->getLength()); } ~DiskWriterEntry() { delete diskWriter; @@ -75,11 +75,12 @@ private: long long int sessionDownloadLength; int pieceLength; int latency; + bool active; public: - Peer(string ipaddr, int port, int pieceLength, long long int totalLength) - :entryId(0), ipaddr(ipaddr), port(port), error(0), + Peer(string ipaddr, int port, int pieceLength, long long int totalLength): + entryId(0), ipaddr(ipaddr), port(port), error(0), sessionUploadLength(0), sessionDownloadLength(0), - pieceLength(pieceLength) + pieceLength(pieceLength), active(false) { resetStatus(); this->bitfield = new BitfieldMan(pieceLength, totalLength); @@ -148,10 +149,16 @@ public: void activate() { peerStat.downloadStart(); + active = true; } void deactivate() { peerStat.downloadStop(); + active = false; + } + + bool isActive() const { + return active; } void setPeerId(const char* peerId) { @@ -193,5 +200,6 @@ public: }; typedef SharedHandle<Peer> PeerHandle; +typedef deque<PeerHandle> Peers; #endif // _D_PEER_H_ diff --git a/src/PeerAbstractCommand.cc b/src/PeerAbstractCommand.cc index 6127450d..37e24c4e 100644 --- a/src/PeerAbstractCommand.cc +++ b/src/PeerAbstractCommand.cc @@ -41,23 +41,25 @@ PeerAbstractCommand::PeerAbstractCommand(int cuid, const PeerHandle& peer, TorrentDownloadEngine* e, + const BtContextHandle& btContext, const SocketHandle& s) - :Command(cuid), e(e), socket(s), peer(peer), - checkSocketIsReadable(false), checkSocketIsWritable(false), - uploadLimitCheck(false), uploadLimit(0), noCheck(false) { + :BtContextAwareCommand(cuid, btContext), e(e), socket(s), peer(peer), + checkSocketIsReadable(false), checkSocketIsWritable(false), + uploadLimitCheck(false), uploadLimit(0), noCheck(false) +{ setReadCheckSocket(socket); timeout = e->option->getAsInt(PREF_TIMEOUT); - e->torrentMan->connections++; + btRuntime->increaseConnections(); } PeerAbstractCommand::~PeerAbstractCommand() { disableReadCheckSocket(); disableWriteCheckSocket(); - e->torrentMan->connections--; + btRuntime->decreaseConnections(); } bool PeerAbstractCommand::execute() { - if(e->torrentMan->isHalt()) { + if(btRuntime->isHalt()) { return true; } try { diff --git a/src/PeerAbstractCommand.h b/src/PeerAbstractCommand.h index 96573d81..52f25520 100644 --- a/src/PeerAbstractCommand.h +++ b/src/PeerAbstractCommand.h @@ -35,12 +35,12 @@ #ifndef _D_PEER_ABSTRACT_COMMAND_H_ #define _D_PEER_ABSTRACT_COMMAND_H_ -#include "Command.h" +#include "BtContextAwareCommand.h" #include "Request.h" #include "TorrentDownloadEngine.h" #include "TimeA2.h" -class PeerAbstractCommand : public Command { +class PeerAbstractCommand : public BtContextAwareCommand { private: Time checkPoint; int timeout; @@ -48,6 +48,7 @@ protected: TorrentDownloadEngine* e; SocketHandle socket; PeerHandle peer; + void setTimeout(int timeout) { this->timeout = timeout; } virtual bool prepareForNextPeer(int wait); virtual bool prepareForRetry(int wait); @@ -71,6 +72,7 @@ private: public: PeerAbstractCommand(int cuid, const PeerHandle& peer, TorrentDownloadEngine* e, + const BtContextHandle& btContext, const SocketHandle& s = SocketHandle()); virtual ~PeerAbstractCommand(); bool execute(); diff --git a/src/PeerChokeCommand.cc b/src/PeerChokeCommand.cc index 4b0cd314..0b49b26d 100644 --- a/src/PeerChokeCommand.cc +++ b/src/PeerChokeCommand.cc @@ -35,7 +35,14 @@ #include "PeerChokeCommand.h" #include "Util.h" -PeerChokeCommand::PeerChokeCommand(int cuid, TorrentDownloadEngine* e, int interval):Command(cuid), interval(interval), e(e), rotate(0) {} +PeerChokeCommand::PeerChokeCommand(int cuid, + TorrentDownloadEngine* e, + const BtContextHandle& btContext, + int interval): + BtContextAwareCommand(cuid, btContext), + interval(interval), + e(e), + rotate(0) {} PeerChokeCommand::~PeerChokeCommand() {} @@ -89,14 +96,14 @@ void PeerChokeCommand::orderByDownloadRate(Peers& peers) const { } bool PeerChokeCommand::execute() { - if(e->torrentMan->isHalt()) { + if(btRuntime->isHalt()) { return true; } if(checkPoint.elapsed(interval)) { checkPoint.reset(); - Peers peers = e->torrentMan->getActivePeers(); + Peers peers = peerStorage->getActivePeers(); for_each(peers.begin(), peers.end(), ChokePeer()); - if(e->torrentMan->downloadComplete()) { + if(pieceStorage->downloadFinished()) { orderByUploadRate(peers); } else { orderByDownloadRate(peers); @@ -109,7 +116,7 @@ bool PeerChokeCommand::execute() { peer->chokingRequired = false; peer->optUnchoking = false; itr = peers.erase(itr); - if(e->torrentMan->downloadComplete()) { + if(pieceStorage->downloadFinished()) { logger->debug("cat01, unchoking %s, upload speed=%d", peer->ipaddr.c_str(), peer->calculateUploadSpeed()); @@ -128,7 +135,7 @@ bool PeerChokeCommand::execute() { peer->chokingRequired = false; peer->optUnchoking = false; itr = peers.erase(itr); - if(e->torrentMan->downloadComplete()) { + if(pieceStorage->downloadFinished()) { logger->debug("cat01, unchoking %s, upload speed=%d", peer->ipaddr.c_str(), peer->calculateUploadSpeed()); diff --git a/src/PeerChokeCommand.h b/src/PeerChokeCommand.h index 8319a269..6b03ccac 100644 --- a/src/PeerChokeCommand.h +++ b/src/PeerChokeCommand.h @@ -35,11 +35,11 @@ #ifndef _D_PEER_CHOKE_COMMAND_H_ #define _D_PEER_CHOKE_COMMAND_H_ -#include "Command.h" +#include "BtContextAwareCommand.h" #include "TorrentDownloadEngine.h" #include "TimeA2.h" -class PeerChokeCommand : public Command { +class PeerChokeCommand : public BtContextAwareCommand { private: int interval; TorrentDownloadEngine* e; @@ -51,7 +51,11 @@ private: void optUnchokingPeer(Peers& peers) const; public: - PeerChokeCommand(int cuid, TorrentDownloadEngine* e, int interval); + PeerChokeCommand(int cuid, + TorrentDownloadEngine* e, + const BtContextHandle& btContext, + int interval); + virtual ~PeerChokeCommand(); bool execute(); diff --git a/src/PeerConnection.h b/src/PeerConnection.h index ab025ee9..de52f004 100644 --- a/src/PeerConnection.h +++ b/src/PeerConnection.h @@ -38,7 +38,6 @@ #include "Option.h" #include "Socket.h" #include "Logger.h" -#include "TorrentMan.h" #include "PeerMessage.h" #include "common.h" diff --git a/src/PeerInitiateConnectionCommand.cc b/src/PeerInitiateConnectionCommand.cc index a578b40e..399cfb1e 100644 --- a/src/PeerInitiateConnectionCommand.cc +++ b/src/PeerInitiateConnectionCommand.cc @@ -41,8 +41,9 @@ PeerInitiateConnectionCommand::PeerInitiateConnectionCommand(int cuid, const PeerHandle& peer, - TorrentDownloadEngine* e) - :PeerAbstractCommand(cuid, peer, e) {} + TorrentDownloadEngine* e, + const BtContextHandle& btContext) + :PeerAbstractCommand(cuid, peer, e, btContext) {} PeerInitiateConnectionCommand::~PeerInitiateConnectionCommand() {} @@ -51,7 +52,13 @@ bool PeerInitiateConnectionCommand::executeInternal() { logger->info(MSG_CONNECTING_TO_SERVER, cuid, peer->ipaddr.c_str(), peer->port); socket->establishConnection(peer->ipaddr, peer->port); - command = new PeerInteractionCommand(cuid, peer, e, socket, PeerInteractionCommand::INITIATOR_SEND_HANDSHAKE); + command = + new PeerInteractionCommand(cuid, + peer, + e, + btContext, + socket, + PeerInteractionCommand::INITIATOR_SEND_HANDSHAKE); e->commands.push_back(command); return true; @@ -59,19 +66,26 @@ bool PeerInitiateConnectionCommand::executeInternal() { // TODO this method removed when PeerBalancerCommand is implemented bool PeerInitiateConnectionCommand::prepareForNextPeer(int wait) { - if(e->torrentMan->isPeerAvailable()) { - PeerHandle peer = e->torrentMan->getPeer(); - int newCuid = e->torrentMan->getNewCuid(); + if(peerStorage->isPeerAvailable() && btRuntime->lessThanEqMinPeer()) { + PeerHandle peer = peerStorage->getUnusedPeer(); + int newCuid = btRuntime->getNewCuid(); peer->cuid = newCuid; PeerInitiateConnectionCommand* command = - new PeerInitiateConnectionCommand(newCuid, peer, e); + new PeerInitiateConnectionCommand(newCuid, + peer, + e, + btContext); e->commands.push_back(command); } return true; } bool PeerInitiateConnectionCommand::prepareForRetry(int wait) { - PeerInitiateConnectionCommand* command = new PeerInitiateConnectionCommand(cuid, peer, e); + PeerInitiateConnectionCommand* command = + new PeerInitiateConnectionCommand(cuid, + peer, + e, + btContext); e->commands.push_back(command); return true; } diff --git a/src/PeerInitiateConnectionCommand.h b/src/PeerInitiateConnectionCommand.h index 15bad8d8..7a86f097 100644 --- a/src/PeerInitiateConnectionCommand.h +++ b/src/PeerInitiateConnectionCommand.h @@ -43,8 +43,11 @@ protected: bool prepareForRetry(int wait); bool prepareForNextPeer(int wait); public: - PeerInitiateConnectionCommand(int cuid, const PeerHandle& peer, - TorrentDownloadEngine* e); + PeerInitiateConnectionCommand(int cuid, + const PeerHandle& peer, + TorrentDownloadEngine* e, + const BtContextHandle& btContext); + ~PeerInitiateConnectionCommand(); }; diff --git a/src/PeerInteraction.cc b/src/PeerInteraction.cc index 50e6fe86..1ec87ce0 100644 --- a/src/PeerInteraction.cc +++ b/src/PeerInteraction.cc @@ -39,20 +39,24 @@ #include "PeerMessageUtil.h" #include "Util.h" #include "prefs.h" +#include "BtRegistry.h" #include <netinet/in.h> PeerInteraction::PeerInteraction(int cuid, const PeerHandle& peer, const SocketHandle& socket, const Option* op, - TorrentMan* torrentMan) + const BtContextHandle& btContext) :cuid(cuid), option(op), - torrentMan(torrentMan), + btContext(btContext), + peerStorage(PEER_STORAGE(btContext)), + pieceStorage(PIECE_STORAGE(btContext)), + btAnnounce(BT_ANNOUNCE(btContext)), peer(peer), quickReplied(false) { peerConnection = new PeerConnection(cuid, socket, op); - peerMessageFactory = new PeerMessageFactory(cuid, this, peer); + peerMessageFactory = new PeerMessageFactory(cuid, btContext, this, peer); logger = LogFactory::getInstance(); } @@ -78,7 +82,7 @@ void PeerInteraction::sendMessages() { PeerMessageHandle msg = messageQueue.front(); messageQueue.pop_front(); if(uploadLimit > 0) { - TransferStat stat = torrentMan->calculateStat(); + TransferStat stat = peerStorage->calculateStat(); if(uploadLimit < stat.uploadSpeed && msg->isUploading() && !msg->isInProgress()) { tempQueue.push_back(msg); @@ -155,7 +159,7 @@ void PeerInteraction::abortPiece(Piece& piece) { itr++; } } - torrentMan->cancelPiece(piece); + pieceStorage->cancelPiece(piece); } } @@ -184,7 +188,7 @@ void PeerInteraction::checkRequestSlot() { } else { Piece piece = getDownloadPiece(slot.getIndex()); if(piece.hasBlock(slot.getBlockIndex()) || - torrentMan->hasPiece(piece.getIndex())) { + pieceStorage->hasPiece(piece.getIndex())) { logger->debug("CUID#%d - Deleting request slot blockIndex=%d because" " the block has been acquired.", cuid, slot.getBlockIndex()); @@ -242,7 +246,7 @@ PeerMessageHandle PeerInteraction::receiveHandshake(bool quickReply) { if(!quickReplied && quickReply && msgLength >= 48) { quickReplied = true; // check info_hash - if(memcmp(torrentMan->getInfoHash(), &msg[28], INFO_HASH_LENGTH) == 0) { + if(memcmp(btContext->getInfoHash(), &msg[28], INFO_HASH_LENGTH) == 0) { sendHandshake(); } } @@ -272,18 +276,18 @@ PeerMessageHandle PeerInteraction::receiveMessage() { void PeerInteraction::syncPiece() { for(Pieces::iterator itr = pieces.begin(); itr != pieces.end(); itr++) { - torrentMan->syncPiece(*itr); + pieceStorage->syncPiece(*itr); } } void PeerInteraction::updatePiece() { for(Pieces::iterator itr = pieces.begin(); itr != pieces.end(); itr++) { - torrentMan->updatePiece(*itr); + pieceStorage->updatePiece(*itr); } } void PeerInteraction::getNewPieceAndSendInterest(int pieceNum) { - if(pieces.empty() && !torrentMan->hasMissingPiece(peer)) { + if(pieces.empty() && !pieceStorage->hasMissingPiece(peer)) { if(peer->amInterested) { logger->debug("CUID#%d - Not interested in the peer", cuid); addMessage(peerMessageFactory->createNotInterestedMessage()); @@ -293,7 +297,7 @@ void PeerInteraction::getNewPieceAndSendInterest(int pieceNum) { onChoked(); if(peer->isFastExtensionEnabled()) { while((int)pieces.size() < pieceNum) { - Piece piece = torrentMan->getMissingFastPiece(peer); + Piece piece = pieceStorage->getMissingFastPiece(peer); if(Piece::isNull(piece)) { break; } else { @@ -303,7 +307,7 @@ void PeerInteraction::getNewPieceAndSendInterest(int pieceNum) { } } else { while((int)pieces.size() < pieceNum) { - Piece piece = torrentMan->getMissingPiece(peer); + Piece piece = pieceStorage->getMissingPiece(peer); if(Piece::isNull(piece)) { break; } else { @@ -338,16 +342,16 @@ void PeerInteraction::addRequests() { MAX_PENDING_REQUEST = 6; } int pieceNum; - if(torrentMan->isEndGame()) { + if(pieceStorage->isEndGame()) { pieceNum = 1; } else { - int blocks = DIV_FLOOR(torrentMan->pieceLength, BLOCK_LENGTH); + int blocks = DIV_FLOOR(btContext->getPieceLength(), BLOCK_LENGTH); pieceNum = DIV_FLOOR(MAX_PENDING_REQUEST, blocks); } getNewPieceAndSendInterest(pieceNum); for(Pieces::iterator itr = pieces.begin(); itr != pieces.end(); itr++) { Piece& piece = *itr; - if(torrentMan->isEndGame()) { + if(pieceStorage->isEndGame()) { BlockIndexes missingBlockIndexes = piece.getAllMissingBlockIndexes(); random_shuffle(missingBlockIndexes.begin(), missingBlockIndexes.end()); int count = countRequestSlot(); @@ -380,23 +384,23 @@ void PeerInteraction::addRequests() { void PeerInteraction::sendHandshake() { PeerMessageHandle handle = - peerMessageFactory->createHandshakeMessage(torrentMan->getInfoHash(), - torrentMan->peerId.c_str()); + peerMessageFactory->createHandshakeMessage(btContext->getInfoHash(), + btAnnounce->getPeerId().c_str()); addMessage(handle); sendMessages(); } void PeerInteraction::sendBitfield() { if(peer->isFastExtensionEnabled()) { - if(torrentMan->hasAllPieces()) { + if(pieceStorage->downloadFinished()) { addMessage(peerMessageFactory->createHaveAllMessage()); - } else if(torrentMan->getDownloadLength() > 0) { + } else if(pieceStorage->getCompletedLength() > 0) { addMessage(peerMessageFactory->createBitfieldMessage()); } else { addMessage(peerMessageFactory->createHaveNoneMessage()); } } else { - if(torrentMan->getDownloadLength() > 0) { + if(pieceStorage->getCompletedLength() > 0) { addMessage(peerMessageFactory->createBitfieldMessage()); } } @@ -405,8 +409,10 @@ void PeerInteraction::sendBitfield() { void PeerInteraction::sendAllowedFast() { if(peer->isFastExtensionEnabled()) { - Integers fastSet = Util::computeFastSet(peer->ipaddr, torrentMan->getInfoHash(), - torrentMan->pieces, ALLOWED_FAST_SET_SIZE); + Integers fastSet = Util::computeFastSet(peer->ipaddr, + btContext->getInfoHash(), + btContext->getNumPieces(), + ALLOWED_FAST_SET_SIZE); for(Integers::const_iterator itr = fastSet.begin(); itr != fastSet.end(); itr++) { addMessage(peerMessageFactory->createAllowedFastMessage(*itr)); diff --git a/src/PeerInteraction.h b/src/PeerInteraction.h index 342f99eb..ef62ba4d 100644 --- a/src/PeerInteraction.h +++ b/src/PeerInteraction.h @@ -37,9 +37,13 @@ #include "common.h" #include "PeerConnection.h" +#include "PeerMessageFactory.h" #include "RequestSlot.h" #include "SharedHandle.h" -#include "PeerMessageFactory.h" +#include "BtContext.h" +#include "PeerStorage.h" +#include "PieceStorage.h" +#include "BtAnnounce.h" #define REQUEST_TIME_OUT 60 #define ALLOWED_FAST_SET_SIZE 10 @@ -53,7 +57,10 @@ private: RequestSlots requestSlots; MessageQueue messageQueue; const Option* option; - TorrentMan* torrentMan; + BtContextHandle btContext; + PeerStorageHandle peerStorage; + PieceStorageHandle pieceStorage; + BtAnnounceHandle btAnnounce; PeerConnection* peerConnection; PeerHandle peer; Pieces pieces; @@ -70,7 +77,7 @@ public: const PeerHandle& peer, const SocketHandle& socket, const Option* op, - TorrentMan* torrentMan); + const BtContextHandle& btContext); ~PeerInteraction(); void addMessage(const PeerMessageHandle& peerMessage); @@ -89,16 +96,20 @@ public: int countMessageInQueue() const; - TorrentMan* getTorrentMan() const { return torrentMan; } + BtContextHandle getBtContext() const { return btContext; } + PeerConnection* getPeerConnection() const { return peerConnection; } + // If this object has nullPiece, then return false, otherwise true bool hasDownloadPiece(int index) const; + // If the piece which this object has is nullPiece, then throws an exception. // So before calling this function, call hasDownloadPiece and make sure // this has valid piece, not nullPiece. Piece& getDownloadPiece(int index); bool isInFastSet(int index) const; + void addFastSetIndex(int index); void syncPiece(); diff --git a/src/PeerInteractionCommand.cc b/src/PeerInteractionCommand.cc index 30d934d9..86a6c3cd 100644 --- a/src/PeerInteractionCommand.cc +++ b/src/PeerInteractionCommand.cc @@ -49,26 +49,27 @@ PeerInteractionCommand::PeerInteractionCommand(int cuid, const PeerHandle& p, TorrentDownloadEngine* e, + const BtContextHandle& btContext, const SocketHandle& s, int sequence) - :PeerAbstractCommand(cuid, p, e, s), sequence(sequence) { + :PeerAbstractCommand(cuid, p, e, btContext, s), sequence(sequence) { if(sequence == INITIATOR_SEND_HANDSHAKE) { disableReadCheckSocket(); setWriteCheckSocket(socket); setTimeout(e->option->getAsInt(PREF_PEER_CONNECTION_TIMEOUT)); } peerInteraction = new PeerInteraction(cuid, peer, socket, e->option, - e->torrentMan); + btContext); setUploadLimit(e->option->getAsInt(PREF_MAX_UPLOAD_LIMIT)); chokeUnchokeCount = 0; haveCount = 0; keepAliveCount = 0; - e->torrentMan->addActivePeer(peer); + peer->activate(); } PeerInteractionCommand::~PeerInteractionCommand() { delete peerInteraction; - e->torrentMan->deleteActivePeer(peer); + peer->deactivate(); } bool PeerInteractionCommand::executeInternal() { @@ -173,7 +174,7 @@ void PeerInteractionCommand::detectMessageFlooding() { /* void PeerInteractionCommand::checkLongTimePeerChoking() { - if(e->torrentMan->downloadComplete()) { + if(pieceStorage->downloadFinished()) { return; } if(peer->amInterested && peer->peerChoking) { @@ -205,7 +206,7 @@ void PeerInteractionCommand::receiveMessages() { for(int i = 0; i < 50; i++) { int maxSpeedLimit = e->option->getAsInt(PREF_MAX_DOWNLOAD_LIMIT); if(maxSpeedLimit > 0) { - TransferStat stat = e->torrentMan->calculateStat(); + TransferStat stat = peerStorage->calculateStat(); if(maxSpeedLimit < stat.downloadSpeed) { disableReadCheckSocket(); setNoCheck(true); @@ -245,12 +246,15 @@ void PeerInteractionCommand::receiveMessages() { // TODO this method removed when PeerBalancerCommand is implemented bool PeerInteractionCommand::prepareForNextPeer(int wait) { - if(e->torrentMan->isPeerAvailable()) { - PeerHandle peer = e->torrentMan->getPeer(); - int newCuid = e->torrentMan->getNewCuid(); + if(peerStorage->isPeerAvailable() && btRuntime->lessThanEqMinPeer()) { + PeerHandle peer = peerStorage->getUnusedPeer(); + int newCuid = btRuntime->getNewCuid(); peer->cuid = newCuid; PeerInitiateConnectionCommand* command = - new PeerInitiateConnectionCommand(newCuid, peer, e); + new PeerInitiateConnectionCommand(newCuid, + peer, + e, + btContext); e->commands.push_back(command); } return true; @@ -278,12 +282,12 @@ void PeerInteractionCommand::sendKeepAlive() { } void PeerInteractionCommand::checkHave() { - PieceIndexes indexes = - e->torrentMan->getAdvertisedPieceIndexes(cuid, haveCheckTime); + Integers indexes = + pieceStorage->getAdvertisedPieceIndexes(cuid, haveCheckTime); haveCheckTime.reset(); if(indexes.size() >= 20) { if(peer->isFastExtensionEnabled()) { - if(e->torrentMan->hasAllPieces()) { + if(pieceStorage->downloadFinished()) { peerInteraction->addMessage(peerInteraction->getPeerMessageFactory()-> createHaveAllMessage()); } else { @@ -295,7 +299,7 @@ void PeerInteractionCommand::checkHave() { createBitfieldMessage()); } } else { - for(PieceIndexes::iterator itr = indexes.begin(); itr != indexes.end(); itr++) { + for(Integers::iterator itr = indexes.begin(); itr != indexes.end(); itr++) { peerInteraction->addMessage(peerInteraction->getPeerMessageFactory()-> createHaveMessage(*itr)); } diff --git a/src/PeerInteractionCommand.h b/src/PeerInteractionCommand.h index 5b0e65cf..73b9fc54 100644 --- a/src/PeerInteractionCommand.h +++ b/src/PeerInteractionCommand.h @@ -73,7 +73,9 @@ protected: public: PeerInteractionCommand(int cuid, const PeerHandle& peer, TorrentDownloadEngine* e, + const BtContextHandle& btContext, const SocketHandle& s, int sequence); + ~PeerInteractionCommand(); enum Seq { diff --git a/src/PeerListProcessor.h b/src/PeerListProcessor.h index 617042af..7a235641 100644 --- a/src/PeerListProcessor.h +++ b/src/PeerListProcessor.h @@ -40,8 +40,6 @@ #include "Peer.h" #include "SharedHandle.h" -typedef deque<PeerHandle> Peers; - class PeerListProcessor { public: virtual ~PeerListProcessor() {} diff --git a/src/PeerListenCommand.cc b/src/PeerListenCommand.cc index ae9bfd9b..d7808127 100644 --- a/src/PeerListenCommand.cc +++ b/src/PeerListenCommand.cc @@ -35,8 +35,11 @@ #include "PeerListenCommand.h" #include "PeerInteractionCommand.h" -PeerListenCommand::PeerListenCommand(int cuid, TorrentDownloadEngine* e) - :Command(cuid), e(e) {} +PeerListenCommand::PeerListenCommand(int cuid, + TorrentDownloadEngine* e, + const BtContextHandle& btContext) + :BtContextAwareCommand(cuid, btContext), + e(e) {} PeerListenCommand::~PeerListenCommand() {} @@ -61,7 +64,7 @@ int PeerListenCommand::bindPort(int portRangeStart, int portRangeEnd) { } bool PeerListenCommand::execute() { - if(e->torrentMan->isHalt()) { + if(btRuntime->isHalt()) { return true; } for(int i = 0; i < 3 && socket->isReadable(0); i++) { @@ -73,15 +76,17 @@ bool PeerListenCommand::execute() { pair<string, int> localInfo; peerSocket->getAddrInfo(localInfo); if(peerInfo.first != localInfo.first && - e->torrentMan->connections < MAX_PEERS) { + btRuntime->getConnections() < MAX_PEERS) { PeerHandle peer = PeerHandle(new Peer(peerInfo.first, peerInfo.second, - e->torrentMan->pieceLength, - e->torrentMan->getTotalLength())); - if(e->torrentMan->addPeer(peer)) { - int newCuid = e->torrentMan->getNewCuid(); + btContext->getPieceLength(), + btContext->getTotalLength())); + if(peerStorage->addPeer(peer)) { + int newCuid = btRuntime->getNewCuid(); peer->cuid = newCuid; PeerInteractionCommand* command = - new PeerInteractionCommand(newCuid, peer, e, peerSocket, + new PeerInteractionCommand(newCuid, peer, e, + btContext, + peerSocket, PeerInteractionCommand::RECEIVER_WAIT_HANDSHAKE); e->commands.push_back(command); logger->debug("CUID#%d - incoming connection, adding new command CUID#%d", cuid, newCuid); diff --git a/src/PeerListenCommand.h b/src/PeerListenCommand.h index a83c1e01..1ae2de91 100644 --- a/src/PeerListenCommand.h +++ b/src/PeerListenCommand.h @@ -35,15 +35,18 @@ #ifndef _D_PEER_LISTEN_COMMAND_H_ #define _D_PEER_LISTEN_COMMAND_H_ -#include "Command.h" +#include "BtContextAwareCommand.h" #include "TorrentDownloadEngine.h" -class PeerListenCommand : public Command { +class PeerListenCommand : public BtContextAwareCommand { private: TorrentDownloadEngine* e; SocketHandle socket; public: - PeerListenCommand(int cuid, TorrentDownloadEngine* e); + PeerListenCommand(int cuid, + TorrentDownloadEngine* e, + const BtContextHandle& btContext); + ~PeerListenCommand(); bool execute(); diff --git a/src/PeerMessage.cc b/src/PeerMessage.cc index d7a16ff2..fe440668 100644 --- a/src/PeerMessage.cc +++ b/src/PeerMessage.cc @@ -38,6 +38,10 @@ PeerMessage::PeerMessage() :inProgress(false), invalidate(false), - uploading(false) { + uploading(false), + btContext(0), + peerStorage(0), + pieceStorage(0) + { logger = LogFactory::getInstance(); } diff --git a/src/PeerMessage.h b/src/PeerMessage.h index 0ef772ff..2d54646b 100644 --- a/src/PeerMessage.h +++ b/src/PeerMessage.h @@ -39,7 +39,10 @@ #include "Logger.h" #include "Peer.h" #include "Piece.h" -#include "SharedHandle.h" +#include "BtContext.h" +#include "PeerStorage.h" +#include "PieceStorage.h" +#include "BtRegistry.h" #include <string> class PeerInteraction; @@ -53,6 +56,9 @@ protected: PeerHandle peer; PeerInteraction* peerInteraction; const Logger* logger; + BtContextHandle btContext; + PeerStorageHandle peerStorage; + PieceStorageHandle pieceStorage; public: PeerMessage(); @@ -63,18 +69,29 @@ public: bool isUploading() const { return uploading; } int getCuid() const { return cuid; } + void setCuid(int cuid) { this->cuid = cuid; } + PeerHandle getPeer() const { return this->peer; } + void setPeer(const PeerHandle& peer) { this->peer = peer; } + PeerInteraction* getPeerInteraction() const { return peerInteraction; } + void setPeerInteraction(PeerInteraction* peerInteraction) { this->peerInteraction = peerInteraction; } + void setBtContext(const BtContextHandle& btContext) { + this->btContext = btContext; + pieceStorage = PIECE_STORAGE(btContext); + peerStorage = PEER_STORAGE(btContext); + } + virtual int getId() const = 0; virtual void receivedAction() = 0; virtual void send() = 0; diff --git a/src/PeerMessageFactory.cc b/src/PeerMessageFactory.cc index 1c031075..95709c8e 100644 --- a/src/PeerMessageFactory.cc +++ b/src/PeerMessageFactory.cc @@ -33,7 +33,6 @@ */ /* copyright --> */ #include "PeerMessageFactory.h" -#include "PeerInteraction.h" #include "PeerMessageUtil.h" #include "ChokeMessage.h" #include "UnchokeMessage.h" @@ -54,11 +53,16 @@ #include "SuggestPieceMessage.h" #include "RequestSlot.h" #include "DlAbortEx.h" +#include "BtRegistry.h" +#include "PeerInteraction.h" PeerMessageFactory::PeerMessageFactory(int cuid, + const BtContextHandle& btContext, PeerInteraction* peerInteraction, const PeerHandle& peer) :cuid(cuid), + btContext(btContext), + pieceStorage(PIECE_STORAGE(btContext)), peerInteraction(peerInteraction), peer(peer) {} @@ -86,29 +90,26 @@ PeerMessageHandle PeerMessageFactory::createPeerMessage(const char* msg, int msg break; case HaveMessage::ID: peerMessage = HaveMessage::create(msg, msgLength); - ((HaveMessage*)peerMessage)->setPieces(peerInteraction->getTorrentMan()-> - pieces); + ((HaveMessage*)peerMessage)->setPieces(btContext->getNumPieces()); break; case BitfieldMessage::ID: peerMessage = BitfieldMessage::create(msg, msgLength); - ((BitfieldMessage*)peerMessage)->setPieces(peerInteraction-> - getTorrentMan()->pieces); + ((BitfieldMessage*)peerMessage)->setPieces(btContext->getNumPieces()); break; case RequestMessage::ID: peerMessage = RequestMessage::create(msg, msgLength); - ((RequestMessage*)peerMessage)->setPieces(peerInteraction-> - getTorrentMan()->pieces); - ((RequestMessage*)peerMessage)->setPieceLength(peerInteraction->getTorrentMan()->getPieceLength(((RequestMessage*)peerMessage)->getIndex())); + ((RequestMessage*)peerMessage)->setPieces(btContext->getNumPieces()); + ((RequestMessage*)peerMessage)->setPieceLength(pieceStorage->getPieceLength(((RequestMessage*)peerMessage)->getIndex())); break; case CancelMessage::ID: peerMessage = CancelMessage::create(msg, msgLength); - ((CancelMessage*)peerMessage)->setPieces(peerInteraction->getTorrentMan()->pieces); - ((CancelMessage*)peerMessage)->setPieceLength(peerInteraction->getTorrentMan()->getPieceLength(((CancelMessage*)peerMessage)->getIndex())); + ((CancelMessage*)peerMessage)->setPieces(btContext->getNumPieces()); + ((CancelMessage*)peerMessage)->setPieceLength(pieceStorage->getPieceLength(((CancelMessage*)peerMessage)->getIndex())); break; case PieceMessage::ID: peerMessage = PieceMessage::create(msg, msgLength); - ((PieceMessage*)peerMessage)->setPieces(peerInteraction->getTorrentMan()->pieces); - ((PieceMessage*)peerMessage)->setPieceLength(peerInteraction->getTorrentMan()->getPieceLength(((PieceMessage*)peerMessage)->getIndex())); + ((PieceMessage*)peerMessage)->setPieces(btContext->getNumPieces()); + ((PieceMessage*)peerMessage)->setPieceLength(pieceStorage->getPieceLength(((PieceMessage*)peerMessage)->getIndex())); break; case PortMessage::ID: peerMessage = PortMessage::create(msg, msgLength); @@ -121,16 +122,16 @@ PeerMessageHandle PeerMessageFactory::createPeerMessage(const char* msg, int msg break; case RejectMessage::ID: peerMessage = RejectMessage::create(msg, msgLength); - ((RejectMessage*)peerMessage)->setPieces(peerInteraction->getTorrentMan()->pieces); - ((RejectMessage*)peerMessage)->setPieceLength(peerInteraction->getTorrentMan()->getPieceLength(((RejectMessage*)peerMessage)->getIndex())); + ((RejectMessage*)peerMessage)->setPieces(btContext->getNumPieces()); + ((RejectMessage*)peerMessage)->setPieceLength(pieceStorage->getPieceLength(((RejectMessage*)peerMessage)->getIndex())); break; case SuggestPieceMessage::ID: peerMessage = SuggestPieceMessage::create(msg, msgLength); - ((SuggestPieceMessage*)peerMessage)->setPieces(peerInteraction->getTorrentMan()->pieces); + ((SuggestPieceMessage*)peerMessage)->setPieces(btContext->getNumPieces()); break; case AllowedFastMessage::ID: peerMessage = AllowedFastMessage::create(msg, msgLength); - ((AllowedFastMessage*)peerMessage)->setPieces(peerInteraction->getTorrentMan()->pieces); + ((AllowedFastMessage*)peerMessage)->setPieces(btContext->getNumPieces()); break; default: throw new DlAbortEx("Invalid message id. id = %d", id); @@ -167,6 +168,7 @@ PeerMessageFactory::setPeerMessageCommonProperty(PeerMessageHandle& peerMessage) peerMessage->setPeer(peer); peerMessage->setCuid(cuid); peerMessage->setPeerInteraction(peerInteraction); + peerMessage->setBtContext(btContext); } PeerMessageHandle PeerMessageFactory::createRequestMessage(const Piece& piece, @@ -235,10 +237,8 @@ PeerMessageHandle PeerMessageFactory::createNotInterestedMessage() const { PeerMessageHandle PeerMessageFactory::createBitfieldMessage() const { PeerMessageHandle handle = - PeerMessageHandle(new BitfieldMessage(peerInteraction->getTorrentMan()-> - getBitfield(), - peerInteraction->getTorrentMan()-> - getBitfieldLength())); + PeerMessageHandle(new BitfieldMessage(pieceStorage->getBitfield(), + pieceStorage->getBitfieldLength())); setPeerMessageCommonProperty(handle); return handle; } diff --git a/src/PeerMessageFactory.h b/src/PeerMessageFactory.h index 147be5c4..481a0b31 100644 --- a/src/PeerMessageFactory.h +++ b/src/PeerMessageFactory.h @@ -38,18 +38,23 @@ #include "common.h" #include "PeerMessage.h" #include "HandshakeMessage.h" +#include "BtContext.h" +#include "PieceStorage.h" class PeerInteraction; class PeerMessageFactory { private: int cuid; + BtContextHandle btContext; + PieceStorageHandle pieceStorage; PeerInteraction* peerInteraction; PeerHandle peer; void setPeerMessageCommonProperty(PeerMessageHandle& peerMessage) const; public: PeerMessageFactory(int cuid, + const BtContextHandle& btContext, PeerInteraction* peerInteraction, const PeerHandle& peer); diff --git a/src/PeerStorage.h b/src/PeerStorage.h new file mode 100644 index 00000000..c5bc49e4 --- /dev/null +++ b/src/PeerStorage.h @@ -0,0 +1,128 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#ifndef _D_PEER_STORAGE_H_ +#define _D_PEER_STORAGE_H_ + +#include "common.h" +#include "Peer.h" + +class TransferStat { +public: + int downloadSpeed; + int uploadSpeed; + long long int sessionDownloadLength; + long long int sessionUploadLength; +public: + TransferStat():downloadSpeed(0), uploadSpeed(0), + sessionDownloadLength(0), sessionUploadLength(0) {} + + int getDownloadSpeed() const { + return downloadSpeed; + } + + void setDownloadSpeed(int s) { downloadSpeed = s; } + + int getUploadSpeed() const { + return uploadSpeed; + } + + void setUploadSpeed(int s) { uploadSpeed = s; } + + /** + * Returns the number of bytes downloaded since the program started. + * This is not the total number of bytes downloaded. + */ + long long int getSessionDownloadLength() const { + return sessionDownloadLength; + } + + void setSessionDownloadLength(long long int s) { sessionDownloadLength = s; } + + /** + * Returns the number of bytes uploaded since the program started. + * This is not the total number of bytes uploaded. + */ + long long int getSessionUploadLength() const { + return sessionUploadLength; + } + + void setSessionUploadLength(long long int s) { sessionUploadLength = s; } +}; + +class PeerStorage { +public: + virtual ~PeerStorage() {} + + /** + * Adds new peer to internal peer list. + * If the peer is added successfully, returns true. Otherwise returns false. + */ + virtual bool addPeer(const PeerHandle& peer) = 0; + + /** + * Adds all peers in peers to internal peer list. + */ + virtual void addPeer(const Peers& peers) = 0; + + /** + * Returns internal peer list. + */ + virtual const Peers& getPeers() = 0; + + /** + * Returns one of the unused peers. + */ + virtual PeerHandle getUnusedPeer() = 0; + + /** + * Returns true if at least one unused peer exists. + * Otherwise returns false. + */ + virtual bool isPeerAvailable() = 0; + + /** + * Returns the list of peers which are currently connected from localhost. + */ + virtual Peers getActivePeers() = 0; + + /** + * Calculates current download/upload statistics. + */ + virtual TransferStat calculateStat() = 0; +}; + +typedef SharedHandle<PeerStorage> PeerStorageHandle; + +#endif // _D_PEER_STORAGE_H_ diff --git a/src/Piece.cc b/src/Piece.cc index 900a4a96..f8d5ed68 100644 --- a/src/Piece.cc +++ b/src/Piece.cc @@ -33,6 +33,7 @@ */ /* copyright --> */ #include "Piece.h" +#include "Util.h" Piece Piece::nullPiece; @@ -79,3 +80,7 @@ int Piece::getMissingBlockIndex() const { BlockIndexes Piece::getAllMissingBlockIndexes() const { return bitfield->getAllMissingIndexes(); } + +string Piece::toString() const { + return "piece: index="+Util::itos(index)+", length="+Util::itos(length); +} diff --git a/src/Piece.h b/src/Piece.h index 4a7c2a6a..f18eae38 100644 --- a/src/Piece.h +++ b/src/Piece.h @@ -117,10 +117,14 @@ public: void clearAllBlock(); void setAllBlock(); + string toString() const; + static Piece nullPiece; static bool isNull(const Piece& piece) { return piece.index == 0 && piece.length == 0; } }; +typedef deque<Piece> Pieces; + #endif // _D_PIECE_H_ diff --git a/src/PieceMessage.cc b/src/PieceMessage.cc index 4c1f414c..367ad2f9 100644 --- a/src/PieceMessage.cc +++ b/src/PieceMessage.cc @@ -65,7 +65,6 @@ PieceMessage* PieceMessage::create(const char* data, int dataLength) { } void PieceMessage::receivedAction() { - TorrentMan* torrentMan = peerInteraction->getTorrentMan(); RequestSlot slot = peerInteraction->getCorrespondingRequestSlot(index, begin, blockLength); @@ -77,15 +76,15 @@ void PieceMessage::receivedAction() { peer->updateLatency(slot.getLatencyInMillis()); Piece& piece = peerInteraction->getDownloadPiece(slot.getIndex()); long long int offset = - ((long long int)index)*torrentMan->pieceLength+begin; + ((long long int)index)*btContext->getPieceLength()+begin; logger->debug("CUID#%d - Writing the block length=%d, offset=%lld", cuid, blockLength, offset); - torrentMan->diskAdaptor->writeData(block, - blockLength, - offset); + pieceStorage->getDiskAdaptor()->writeData(block, + blockLength, + offset); piece.completeBlock(slot.getBlockIndex()); peerInteraction->deleteRequestSlot(slot); - torrentMan->updatePiece(piece); + pieceStorage->updatePiece(piece); logger->debug("CUID#%d - Setting piece block index=%d", cuid, slot.getBlockIndex()); if(piece.pieceComplete()) { @@ -123,7 +122,6 @@ void PieceMessage::send() { if(invalidate) { return; } - TorrentMan* torrentMan = peerInteraction->getTorrentMan(); PeerConnection* peerConnection = peerInteraction->getPeerConnection(); if(!headerSent) { if(!inProgress) { @@ -146,13 +144,11 @@ void PieceMessage::send() { } if(headerSent) { inProgress = false; - int pieceLength = torrentMan->pieceLength; long long int pieceDataOffset = - ((long long int)index)*pieceLength+begin+blockLength-leftDataLength; + ((long long int)index)*btContext->getPieceLength()+begin+blockLength-leftDataLength; int writtenLength = sendPieceData(pieceDataOffset, leftDataLength); peer->updateUploadLength(writtenLength); - torrentMan->addUploadLength(writtenLength); if(writtenLength != leftDataLength) { inProgress = true; } @@ -165,10 +161,9 @@ int PieceMessage::sendPieceData(long long int offset, int length) const { char buf[BUF_SIZE]; int iteration = length/BUF_SIZE; int writtenLength = 0; - TorrentMan* torrentMan = peerInteraction->getTorrentMan(); PeerConnection* peerConnection = peerInteraction->getPeerConnection(); for(int i = 0; i < iteration; i++) { - if(torrentMan->diskAdaptor->readData(buf, BUF_SIZE, offset+i*BUF_SIZE) < BUF_SIZE) { + if(pieceStorage->getDiskAdaptor()->readData(buf, BUF_SIZE, offset+i*BUF_SIZE) < BUF_SIZE) { throw new DlAbortEx("Failed to read data from disk."); } int ws = peerConnection->sendMessage(buf, BUF_SIZE); @@ -181,7 +176,7 @@ int PieceMessage::sendPieceData(long long int offset, int length) const { int rem = length%BUF_SIZE; if(rem > 0) { - if(torrentMan->diskAdaptor->readData(buf, rem, offset+iteration*BUF_SIZE) < rem) { + if(pieceStorage->getDiskAdaptor()->readData(buf, rem, offset+iteration*BUF_SIZE) < rem) { throw new DlAbortEx("Failed to read data from disk."); } int ws = peerConnection->sendMessage(buf, rem); @@ -202,42 +197,39 @@ string PieceMessage::toString() const { } bool PieceMessage::checkPieceHash(const Piece& piece) { - TorrentMan* torrentMan = peerInteraction->getTorrentMan(); long long int offset = - ((long long int)piece.getIndex())*torrentMan->pieceLength; - return torrentMan->diskAdaptor->sha1Sum(offset, piece.getLength()) == - torrentMan->getPieceHash(piece.getIndex()); + ((long long int)piece.getIndex())*btContext->getPieceLength(); + return pieceStorage->getDiskAdaptor()->sha1Sum(offset, piece.getLength()) == + btContext->getPieceHash(piece.getIndex()); } void PieceMessage::onGotNewPiece(Piece& piece) { - TorrentMan* torrentMan = peerInteraction->getTorrentMan(); logger->info(MSG_GOT_NEW_PIECE, cuid, piece.getIndex()); - torrentMan->completePiece(piece); - torrentMan->advertisePiece(cuid, piece.getIndex()); + pieceStorage->completePiece(piece); + pieceStorage->advertisePiece(cuid, piece.getIndex()); } void PieceMessage::onGotWrongPiece(Piece& piece) { - TorrentMan* torrentMan = peerInteraction->getTorrentMan(); logger->error(MSG_GOT_WRONG_PIECE, cuid, piece.getIndex()); erasePieceOnDisk(piece); piece.clearAllBlock(); - torrentMan->updatePiece(piece); + pieceStorage->updatePiece(piece); peerInteraction->abortPiece(piece); } void PieceMessage::erasePieceOnDisk(const Piece& piece) { - TorrentMan* torrentMan = peerInteraction->getTorrentMan(); int BUFSIZE = 4096; char buf[BUFSIZE]; memset(buf, 0, BUFSIZE); - long long int offset = ((long long int)piece.getIndex())*torrentMan->pieceLength; + long long int offset = + ((long long int)piece.getIndex())*btContext->getPieceLength(); for(int i = 0; i < piece.getLength()/BUFSIZE; i++) { - torrentMan->diskAdaptor->writeData(buf, BUFSIZE, offset); + pieceStorage->getDiskAdaptor()->writeData(buf, BUFSIZE, offset); offset += BUFSIZE; } int r = piece.getLength()%BUFSIZE; if(r > 0) { - torrentMan->diskAdaptor->writeData(buf, r, offset); + pieceStorage->getDiskAdaptor()->writeData(buf, r, offset); } } diff --git a/src/PieceMessage.h b/src/PieceMessage.h index 90f5b0b7..328ff7bd 100644 --- a/src/PieceMessage.h +++ b/src/PieceMessage.h @@ -36,7 +36,6 @@ #define _D_PIECE_MESSAGE_H_ #include "PeerMessage.h" -#include "TorrentMan.h" class PieceMessage : public PeerMessage { private: diff --git a/src/PieceStorage.h b/src/PieceStorage.h new file mode 100644 index 00000000..4ee76e05 --- /dev/null +++ b/src/PieceStorage.h @@ -0,0 +1,157 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#ifndef _D_PIECE_STORAGE_H_ +#define _D_PIECE_STORAGE_H_ + +#include "common.h" +#include "Peer.h" +#include "Piece.h" +#include "DiskAdaptor.h" + +class PieceStorage { +public: + virtual ~PieceStorage() {} + + /** + * Returns true if the peer has a piece that localhost doesn't have. + * Otherwise returns false. + */ + virtual bool hasMissingPiece(const PeerHandle& peer) = 0; + + /** + * Returns a piece that the peer has but localhost doesn't. + * The piece will be marked "used" status in order to prevent other command + * from get the same piece. But in end game mode, same piece may be returned + * to several commands. + */ + virtual Piece getMissingPiece(const PeerHandle& peer) = 0; + /** + * Returns a piece that the peer has but localhost doesn't. + * Only pieces that declared as "fast" are returned. + * The piece will be marked "used" status in order to prevent other command + * from get the same piece. But in end game mode, same piece may be returned + * to several commands. + */ + virtual Piece getMissingFastPiece(const PeerHandle& peer) = 0; + + /** + * Tells that the download of the specfied piece completes. + */ + virtual void completePiece(const Piece& piece) = 0; + + /** + * Tells that the download of the specified piece is canceled. + */ + virtual void cancelPiece(const Piece& piece) = 0; + + /** + * Updates the internal piece data with the specified piece data. + */ + virtual void updatePiece(const Piece& piece) = 0; + + /** + * Updates the spcefied piece data with the internal piece data. + */ + virtual void syncPiece(Piece& piece) = 0; + + /** + * Returns true if the specified piece is already downloaded. + * Otherwise returns false. + */ + virtual bool hasPiece(int index) = 0; + + virtual long long int getTotalLength() = 0; + + virtual long long int getFilteredTotalLength() = 0; + + virtual long long int getCompletedLength() = 0; + + virtual long long int getFilteredCompletedLength() = 0; + + virtual void setFileFilter(const Strings& filePaths) = 0; + + virtual void setFileFilter(const Integers& fileIndexes) = 0; + + virtual void clearFileFilter() = 0; + + virtual bool downloadFinished() = 0; + + /** + * Initializes DiskAdaptor. + * TODO add better documentation here. + */ + virtual void initStorage() = 0; + + virtual const unsigned char* getBitfield() = 0; + + virtual void setBitfield(const unsigned char* bitfield, + int bitfieldLength) = 0; + + virtual int getBitfieldLength() = 0; + + virtual bool isSelectiveDownloadingMode() = 0; + + virtual void finishSelectiveDownloadingMode() = 0; + + virtual bool isEndGame() = 0; + + virtual DiskAdaptor* getDiskAdaptor() = 0; + + virtual int getPieceLength(int index) = 0; + + /** + * Adds piece index to advertise to other commands. They send have message + * based on this information. + */ + virtual void advertisePiece(int cuid, int index) = 0; + + /** + * Returns piece index which is not advertised by the caller command and + * newer than lastCheckTime. + */ + virtual Integers getAdvertisedPieceIndexes(int myCuid, + const Time& lastCheckTime) = 0; + + /** + * Removes have entry if specified seconds have elapsed since its + * registration. + */ + virtual void removeAdvertisedPiece(int elapsed) = 0; + +}; + +typedef SharedHandle<PieceStorage> PieceStorageHandle; + +#endif // _D_PIECE_STORAGE_H_ diff --git a/src/RejectMessage.h b/src/RejectMessage.h index 7d2b43cf..5b33d37e 100644 --- a/src/RejectMessage.h +++ b/src/RejectMessage.h @@ -36,7 +36,6 @@ #define _D_REJECT_MESSAGE_H_ #include "SimplePeerMessage.h" -#include "TorrentMan.h" class RejectMessage : public SimplePeerMessage { private: diff --git a/src/RequestMessage.cc b/src/RequestMessage.cc index 62c68427..0ab6e343 100644 --- a/src/RequestMessage.cc +++ b/src/RequestMessage.cc @@ -55,8 +55,7 @@ RequestMessage* RequestMessage::create(const char* data, int dataLength) { } void RequestMessage::receivedAction() { - TorrentMan* torrentMan = peerInteraction->getTorrentMan(); - if(torrentMan->hasPiece(index) && + if(pieceStorage->hasPiece(index) && (!peer->amChoking || peer->amChoking && peerInteraction->isInFastSet(index))) { peerInteraction->addMessage(peerInteraction->getPeerMessageFactory()-> diff --git a/src/RequestMessage.h b/src/RequestMessage.h index 68d20d77..7c7c7b20 100644 --- a/src/RequestMessage.h +++ b/src/RequestMessage.h @@ -36,7 +36,6 @@ #define _D_REQUEST_MESSAGE_H_ #include "SimplePeerMessage.h" -#include "TorrentMan.h" class RequestMessage : public SimplePeerMessage { private: diff --git a/src/SeedCheckCommand.cc b/src/SeedCheckCommand.cc index 51de429d..ae869724 100644 --- a/src/SeedCheckCommand.cc +++ b/src/SeedCheckCommand.cc @@ -34,8 +34,17 @@ /* copyright --> */ #include "SeedCheckCommand.h" +SeedCheckCommand::SeedCheckCommand(int cuid, + TorrentDownloadEngine* e, + const BtContextHandle& btContext, + SeedCriteriaHandle seedCriteria) + :BtContextAwareCommand(cuid, btContext), + e(e), + seedCriteria(seedCriteria), + checkStarted(false) {} + bool SeedCheckCommand::execute() { - if(e->torrentMan->isHalt()) { + if(btRuntime->isHalt()) { return true; } if(!seedCriteria.get()) { @@ -43,7 +52,7 @@ bool SeedCheckCommand::execute() { } if(checkPoint.elapsed(1)) { if(!checkStarted) { - if(e->torrentMan->downloadComplete()) { + if(pieceStorage->downloadFinished()) { checkStarted = true; seedCriteria->reset(); } @@ -51,7 +60,7 @@ bool SeedCheckCommand::execute() { if(checkStarted) { if(seedCriteria->evaluate()) { logger->notice("CUID#%d - Seeding is over.", cuid); - e->torrentMan->setHalt(true); + btRuntime->setHalt(true); } } } diff --git a/src/SeedCheckCommand.h b/src/SeedCheckCommand.h index 5e4f92bb..4ade4094 100644 --- a/src/SeedCheckCommand.h +++ b/src/SeedCheckCommand.h @@ -35,24 +35,22 @@ #ifndef _D_SEED_CHECK_COMMAND_H_ #define _D_SEED_CHECK_COMMAND_H_ -#include "Command.h" +#include "BtContextAwareCommand.h" #include "TorrentDownloadEngine.h" #include "TimeA2.h" #include "SeedCriteria.h" -class SeedCheckCommand : public Command { +class SeedCheckCommand : public BtContextAwareCommand { private: TorrentDownloadEngine* e; Time checkPoint; SeedCriteriaHandle seedCriteria; bool checkStarted; public: - SeedCheckCommand(int cuid, TorrentDownloadEngine* e, - SeedCriteriaHandle seedCriteria) - :Command(cuid), - e(e), - seedCriteria(seedCriteria), - checkStarted(false) {} + SeedCheckCommand(int cuid, + TorrentDownloadEngine* e, + const BtContextHandle& btContext, + SeedCriteriaHandle seedCriteria); virtual ~SeedCheckCommand() {} diff --git a/src/ShareRatioSeedCriteria.h b/src/ShareRatioSeedCriteria.h index 72f32227..6ded3b02 100644 --- a/src/ShareRatioSeedCriteria.h +++ b/src/ShareRatioSeedCriteria.h @@ -36,26 +36,37 @@ #define _D_SHARE_RATIO_SEED_CRITERIA_H_ #include "SeedCriteria.h" -#include "TorrentMan.h" +#include "BtContext.h" +#include "PeerStorage.h" +#include "BtRuntime.h" +#include "BtRegistry.h" class ShareRatioSeedCriteria : public SeedCriteria { private: double ratio; - TorrentMan* torrentMan; + BtContextHandle btContext; + PeerStorageHandle peerStorage; + BtRuntimeHandle btRuntime; public: - ShareRatioSeedCriteria(double ratio, TorrentMan* torrentMan) + ShareRatioSeedCriteria(double ratio, const BtContextHandle& btContext) :ratio(ratio), - torrentMan(torrentMan) {} + btContext(btContext), + peerStorage(PEER_STORAGE(btContext)), + btRuntime(BT_RUNTIME(btContext)) {} + virtual ~ShareRatioSeedCriteria() {} virtual void reset() {} virtual bool evaluate() { - if(torrentMan->getDownloadLength() == 0) { + if(btContext->getTotalLength() == 0) { return false; } + TransferStat stat = peerStorage->calculateStat(); + long long int allTimeUploadLength = + btRuntime->getUploadLengthAtStartup()+stat.getSessionUploadLength(); return ratio <= - ((double)torrentMan->getUploadLength())/torrentMan->getDownloadLength(); + ((double)allTimeUploadLength)/btContext->getTotalLength(); } void setRatio(double ratio) { diff --git a/src/TorrentAutoSaveCommand.cc b/src/TorrentAutoSaveCommand.cc index 5d2154c3..b363e3ca 100644 --- a/src/TorrentAutoSaveCommand.cc +++ b/src/TorrentAutoSaveCommand.cc @@ -35,15 +35,21 @@ #include "TorrentAutoSaveCommand.h" #include "Util.h" -TorrentAutoSaveCommand::TorrentAutoSaveCommand(int cuid, TorrentDownloadEngine* e, int interval):Command(cuid), e(e), interval(interval) {} +TorrentAutoSaveCommand::TorrentAutoSaveCommand(int cuid, + TorrentDownloadEngine* e, + const BtContextHandle& btContext, + int interval): + BtContextAwareCommand(cuid, btContext), + e(e), + interval(interval) {} TorrentAutoSaveCommand::~TorrentAutoSaveCommand() {} bool TorrentAutoSaveCommand::execute() { - if(checkPoint.elapsed(interval) || e->torrentMan->isHalt()) { + if(checkPoint.elapsed(interval) || btRuntime->isHalt()) { checkPoint.reset(); - e->torrentMan->save(); - if(e->torrentMan->isHalt()) { + btProgressInfoFile->save(); + if(btRuntime->isHalt()) { return true; } } diff --git a/src/TorrentAutoSaveCommand.h b/src/TorrentAutoSaveCommand.h index 9c360020..d0f511a3 100644 --- a/src/TorrentAutoSaveCommand.h +++ b/src/TorrentAutoSaveCommand.h @@ -35,17 +35,22 @@ #ifndef _D_TORRENT_AUTO_SAVE_COMMAND_H_ #define _D_TORRENT_AUTO_SAVE_COMMAND_H_ -#include "Command.h" +#include "BtContextAwareCommand.h" #include "TorrentDownloadEngine.h" #include "TimeA2.h" +#include "BtContext.h" -class TorrentAutoSaveCommand : public Command { +class TorrentAutoSaveCommand : public BtContextAwareCommand { private: TorrentDownloadEngine* e; int interval; Time checkPoint; public: - TorrentAutoSaveCommand(int cuid, TorrentDownloadEngine* e, int interval); + TorrentAutoSaveCommand(int cuid, + TorrentDownloadEngine* e, + const BtContextHandle& btContext, + int interval); + ~TorrentAutoSaveCommand(); bool execute(); diff --git a/src/TorrentConsoleDownloadEngine.cc b/src/TorrentConsoleDownloadEngine.cc index 3f6ab8b1..e697c718 100644 --- a/src/TorrentConsoleDownloadEngine.cc +++ b/src/TorrentConsoleDownloadEngine.cc @@ -34,6 +34,9 @@ /* copyright --> */ #include "TorrentConsoleDownloadEngine.h" #include "Util.h" +#include <signal.h> + +volatile sig_atomic_t haltRequested = 0; TorrentConsoleDownloadEngine::TorrentConsoleDownloadEngine() {} @@ -42,8 +45,8 @@ TorrentConsoleDownloadEngine::~TorrentConsoleDownloadEngine() {} void TorrentConsoleDownloadEngine::sendStatistics() { printf("\r "); printf("\r"); - if(torrentMan->downloadComplete()) { - printf("Download Completed "); + if(pieceStorage->downloadFinished()) { + printf("Download Completed."); } else { printf("%s/%sB %d%% %s D:%.2f", Util::llitos(downloadLength, true).c_str(), @@ -55,7 +58,14 @@ void TorrentConsoleDownloadEngine::sendStatistics() { } printf(" U:%.2f(%s) %d peers", uploadSpeed/1024.0, - Util::llitos(torrentMan->getUploadLength(), true).c_str(), - torrentMan->connections); + Util::llitos(uploadLength, true).c_str(), + btRuntime->getConnections()); fflush(stdout); } + +void TorrentConsoleDownloadEngine::afterEachIteration() { + if(haltRequested) { + btRuntime->setHalt(true); + } + TorrentDownloadEngine::afterEachIteration(); +} diff --git a/src/TorrentConsoleDownloadEngine.h b/src/TorrentConsoleDownloadEngine.h index 2bbd1f0f..dea43c82 100644 --- a/src/TorrentConsoleDownloadEngine.h +++ b/src/TorrentConsoleDownloadEngine.h @@ -43,6 +43,8 @@ protected: public: TorrentConsoleDownloadEngine(); ~TorrentConsoleDownloadEngine(); + + virtual void afterEachIteration(); }; #endif // _D_TORRENT_CONSOLE_DOWNLOAD_ENGINE_H_ diff --git a/src/TorrentDownloadEngine.cc b/src/TorrentDownloadEngine.cc index 974c1995..30a0587c 100644 --- a/src/TorrentDownloadEngine.cc +++ b/src/TorrentDownloadEngine.cc @@ -34,22 +34,35 @@ /* copyright --> */ #include "TorrentDownloadEngine.h" #include "Util.h" +#include "BtRegistry.h" -TorrentDownloadEngine::TorrentDownloadEngine():filenameFixed(false), - torrentMan(NULL) {} +TorrentDownloadEngine::TorrentDownloadEngine(): + filenameFixed(false), + btContext(0), + btRuntime(0), + pieceStorage(0), + peerStorage(0), + btAnnounce(0), + btProgressInfoFile(0) {} TorrentDownloadEngine::~TorrentDownloadEngine() { - if(torrentMan != NULL) { - delete torrentMan; - } +} + +void TorrentDownloadEngine::setBtContext(const BtContextHandle& btContext) { + this->btContext = btContext; + btRuntime = BT_RUNTIME(btContext); + pieceStorage = PIECE_STORAGE(btContext); + peerStorage = PEER_STORAGE(btContext); + btAnnounce = BT_ANNOUNCE(btContext); + btProgressInfoFile = BT_PROGRESS_INFO_FILE(btContext); } void TorrentDownloadEngine::onEndOfRun() { - torrentMan->diskAdaptor->closeFile(); - if(torrentMan->downloadComplete()) { - torrentMan->remove(); + pieceStorage->getDiskAdaptor()->closeFile(); + if(pieceStorage->downloadFinished()) { + btProgressInfoFile->removeFile(); } else { - torrentMan->save(); + btProgressInfoFile->save(); } } @@ -57,16 +70,12 @@ void TorrentDownloadEngine::initStatistics() { downloadSpeed = 0; uploadSpeed = 0; cp.reset(); - lastCalcStat.reset(); startup.reset(); eta = 0; avgSpeed = 0; downloadLength = 0; + uploadLength = 0; totalLength = 0; - if(torrentMan->isSelectiveDownloadingMode()) { - selectedDownloadLengthDiff = torrentMan->getDownloadLength()-torrentMan->getCompletedLength(); - selectedTotalLength = torrentMan->getSelectedTotalLength(); - } } int TorrentDownloadEngine::calculateSpeed(long long int length, int elapsed) { @@ -75,10 +84,22 @@ int TorrentDownloadEngine::calculateSpeed(long long int length, int elapsed) { } void TorrentDownloadEngine::calculateStat() { - TransferStat stat = torrentMan->calculateStat(); - downloadSpeed = stat.downloadSpeed; - uploadSpeed = stat.uploadSpeed; - avgSpeed = calculateSpeed(stat.sessionDownloadLength, startup.difference()); + TransferStat stat = peerStorage->calculateStat(); + + if(pieceStorage->isSelectiveDownloadingMode()) { + downloadLength = pieceStorage->getFilteredCompletedLength(); + totalLength = pieceStorage->getFilteredTotalLength(); + } else { + downloadLength = pieceStorage->getCompletedLength(); + totalLength = pieceStorage->getTotalLength(); + } + uploadLength = stat.getSessionUploadLength()+ + btRuntime->getUploadLengthAtStartup(); + + downloadSpeed = stat.getDownloadSpeed(); + uploadSpeed = stat.getUploadSpeed(); + avgSpeed = calculateSpeed(stat.getSessionDownloadLength(), + startup.difference()); if(avgSpeed < 0) { avgSpeed = 0; } else if(avgSpeed != 0) { @@ -87,20 +108,8 @@ void TorrentDownloadEngine::calculateStat() { } void TorrentDownloadEngine::calculateStatistics() { - if(torrentMan->isSelectiveDownloadingMode()) { - downloadLength = torrentMan->getDownloadLength()-selectedDownloadLengthDiff; - totalLength = selectedTotalLength; - } else { - downloadLength = torrentMan->getDownloadLength(); - totalLength = torrentMan->getTotalLength(); - } - - Time now; - if(now.getTimeInMillis()-lastCalcStat.getTimeInMillis() >= 1000) { - calculateStat(); - lastCalcStat = now; - } if(cp.difference() >= 1) { + calculateStat(); sendStatistics(); cp.reset(); } diff --git a/src/TorrentDownloadEngine.h b/src/TorrentDownloadEngine.h index b9ac9f67..f87cd32e 100644 --- a/src/TorrentDownloadEngine.h +++ b/src/TorrentDownloadEngine.h @@ -36,8 +36,13 @@ #define _D_TORRENT_DOWNLOAD_ENGINE_H_ #include "DownloadEngine.h" -#include "TorrentMan.h" #include "TimeA2.h" +#include "BtContext.h" +#include "BtRuntime.h" +#include "PieceStorage.h" +#include "PeerStorage.h" +#include "BtAnnounce.h" +#include "BtProgressInfoFile.h" class TorrentDownloadEngine : public DownloadEngine { private: @@ -59,8 +64,16 @@ protected: // The estimated remaining time to complete the download. int eta; long long int downloadLength; + long long int uploadLength; long long int totalLength; + BtContextHandle btContext; + BtRuntimeHandle btRuntime; + PieceStorageHandle pieceStorage; + PeerStorageHandle peerStorage; + BtAnnounceHandle btAnnounce; + BtProgressInfoFileHandle btProgressInfoFile; + int calculateSpeed(long long int sessionLength, int elapsed); void calculateStat(); @@ -70,9 +83,9 @@ public: TorrentDownloadEngine(); virtual ~TorrentDownloadEngine(); - TorrentMan* torrentMan; - bool isFilenameFixed() const { return filenameFixed; } + + void setBtContext(const BtContextHandle& btContext); }; #endif // _D_TORRENT_DOWNLOAD_ENGINE_H_ diff --git a/src/TorrentRequestInfo.cc b/src/TorrentRequestInfo.cc index 3760da2e..d2ba00d1 100644 --- a/src/TorrentRequestInfo.cc +++ b/src/TorrentRequestInfo.cc @@ -36,19 +36,24 @@ #include "DownloadEngineFactory.h" #include "prefs.h" #include "Util.h" +#include "BtRegistry.h" +#include "DefaultBtContext.h" extern RequestInfo* requestInfo; extern void setSignalHander(int signal, void (*handler)(int), int flags); extern bool timeoutSpecified; +extern volatile sig_atomic_t haltRequested; void torrentHandler(int signal) { - ((TorrentDownloadEngine*)requestInfo->getDownloadEngine())-> - torrentMan->setHalt(true); + haltRequested = 1; } RequestInfo* TorrentRequestInfo::execute() { + BtContextHandle btContext(new DefaultBtContext()); + btContext->load(torrentFile); + if(op->get(PREF_SHOW_FILES) == V_TRUE) { - showFileEntry(); + showFileEntry(btContext); return 0; } if(!timeoutSpecified) { @@ -56,45 +61,42 @@ RequestInfo* TorrentRequestInfo::execute() { } // set max_tries to 1. AnnounceList handles retries. op->put(PREF_MAX_TRIES, "1"); - e = DownloadEngineFactory::newTorrentConsoleEngine(op, - torrentFile, - targetFiles); + SharedHandle<TorrentDownloadEngine> + e(DownloadEngineFactory::newTorrentConsoleEngine(btContext, + op, + targetFiles)); + setSignalHander(SIGINT, torrentHandler, SA_RESETHAND); setSignalHander(SIGTERM, torrentHandler, SA_RESETHAND); try { e->run(); - if(e->torrentMan->downloadComplete()) { + if(PIECE_STORAGE(btContext)->downloadFinished()) { printDownloadCompeleteMessage(); } - } catch(Exception* e) { - logger->error("Exception caught", e); - delete e; + } catch(Exception* ex) { + logger->error("Exception caught", ex); fail = true; + delete ex; } setSignalHander(SIGINT, SIG_DFL, 0); setSignalHander(SIGTERM, SIG_DFL, 0); - delete e; return 0; } -// TODO should be const TorrentMan* torrentMan -void TorrentRequestInfo::showFileEntry() +void TorrentRequestInfo::showFileEntry(const BtContextHandle& btContext) { - TorrentMan torrentMan; - torrentMan.option = op; - - FileEntries fileEntries = - torrentMan.readFileEntryFromMetaInfoFile(torrentFile); + FileEntries fileEntries = btContext->getFileEntries(); cout << _("Files:") << endl; cout << "idx|path/length" << endl; cout << "===+===========================================================================" << endl; int count = 1; for(FileEntries::const_iterator itr = fileEntries.begin(); itr != fileEntries.end(); count++, itr++) { - printf("%3d|%s\n |%s Bytes\n", count, itr->path.c_str(), - Util::llitos(itr->length, true).c_str()); + printf("%3d|%s\n |%s Bytes\n", count, + (*itr)->getPath().c_str(), + Util::llitos((*itr)->getLength(), true).c_str()); cout << "---+---------------------------------------------------------------------------" << endl; } } diff --git a/src/TorrentRequestInfo.h b/src/TorrentRequestInfo.h index 4c6266c4..82013467 100644 --- a/src/TorrentRequestInfo.h +++ b/src/TorrentRequestInfo.h @@ -37,19 +37,19 @@ #include "RequestInfo.h" #include "TorrentDownloadEngine.h" +#include "BtContext.h" class TorrentRequestInfo : public RequestInfo { private: string torrentFile; - TorrentDownloadEngine* e; Strings targetFiles; - void showFileEntry(); + void showFileEntry(const BtContextHandle& btContext); public: TorrentRequestInfo(const string& torrentFile, Option* op): RequestInfo(op), - torrentFile(torrentFile), - e(0) {} + torrentFile(torrentFile) {} + virtual ~TorrentRequestInfo() {} virtual RequestInfo* execute(); @@ -57,8 +57,10 @@ public: void setTargetFiles(const Strings& targetFiles) { this->targetFiles = targetFiles; } - virtual DownloadEngine* getDownloadEngine() { return e; } + virtual DownloadEngine* getDownloadEngine() { + return 0; + } }; #endif // _D_TORRENT_REQUEST_INFO_H_ diff --git a/src/TrackerUpdateCommand.cc b/src/TrackerUpdateCommand.cc index 1fdebc96..eebe71b4 100644 --- a/src/TrackerUpdateCommand.cc +++ b/src/TrackerUpdateCommand.cc @@ -40,7 +40,13 @@ #include "SleepCommand.h" #include "Util.h" -TrackerUpdateCommand::TrackerUpdateCommand(int cuid, TorrentDownloadEngine* e):Command(cuid), e(e) { +extern PeerHandle nullPeer; + +TrackerUpdateCommand::TrackerUpdateCommand(int cuid, + TorrentDownloadEngine* e, + const BtContextHandle& btContext): + BtContextAwareCommand(cuid, btContext), e(e) +{ logger = LogFactory::getInstance(); } @@ -77,7 +83,7 @@ char* TrackerUpdateCommand::getTrackerResponse(size_t& trackerResponseLength) { } bool TrackerUpdateCommand::execute() { - if(e->segmentMan->errors > 0 && e->torrentMan->isHalt()) { + if(e->segmentMan->errors > 0 && btRuntime->isHalt()) { return true; } if(!e->segmentMan->finished()) { @@ -89,19 +95,25 @@ bool TrackerUpdateCommand::execute() { try { trackerResponse = getTrackerResponse(trackerResponseLength); - e->torrentMan->processAnnounceResponse(trackerResponse, - trackerResponseLength); - while(e->torrentMan->needMorePeerConnection()) { - PeerHandle peer = e->torrentMan->getPeer(); - int newCuid = e->torrentMan->getNewCuid(); + btAnnounce->processAnnounceResponse(trackerResponse, + trackerResponseLength); + while(!btRuntime->isHalt() && btRuntime->lessThanMinPeer()) { + PeerHandle peer = peerStorage->getUnusedPeer(); + if(peer == nullPeer) { + break; + } + int newCuid = btRuntime->getNewCuid(); peer->cuid = newCuid; PeerInitiateConnectionCommand* command = - new PeerInitiateConnectionCommand(newCuid, peer, e); + new PeerInitiateConnectionCommand(newCuid, + peer, + e, + btContext); e->commands.push_back(command); logger->debug("CUID#%d - Adding new command CUID#%d", cuid, newCuid); } - e->torrentMan->announceSuccess(); - e->torrentMan->resetAnnounce(); + btAnnounce->announceSuccess(); + btAnnounce->resetAnnounce(); e->segmentMan->init(); } catch(Exception* err) { logger->error("CUID#%d - Error occurred while processing tracker response.", cuid, err); @@ -111,7 +123,7 @@ bool TrackerUpdateCommand::execute() { if(trackerResponse) { delete [] trackerResponse; } - if(e->torrentMan->isHalt()) { + if(btRuntime->isHalt()) { return true; } else { return prepareForRetry(); diff --git a/src/TrackerUpdateCommand.h b/src/TrackerUpdateCommand.h index a4a0ad10..13dd5796 100644 --- a/src/TrackerUpdateCommand.h +++ b/src/TrackerUpdateCommand.h @@ -35,18 +35,21 @@ #ifndef _D_TRACKER_UPDATE_COMMAND_H_ #define _D_TRACKER_UPDATE_COMMAND_H_ -#include "Command.h" +#include "BtContextAwareCommand.h" #include "TorrentDownloadEngine.h" #include "Logger.h" -class TrackerUpdateCommand : public Command { +class TrackerUpdateCommand : public BtContextAwareCommand { private: TorrentDownloadEngine* e; const Logger* logger; bool prepareForRetry(); char* getTrackerResponse(size_t& trackerResponseLength); public: - TrackerUpdateCommand(int cuid, TorrentDownloadEngine* e); + TrackerUpdateCommand(int cuid, + TorrentDownloadEngine* e, + const BtContextHandle& btContext); + virtual ~TrackerUpdateCommand(); bool execute(); diff --git a/src/TrackerWatcherCommand.cc b/src/TrackerWatcherCommand.cc index cea9a914..825def5d 100644 --- a/src/TrackerWatcherCommand.cc +++ b/src/TrackerWatcherCommand.cc @@ -39,17 +39,19 @@ #include "prefs.h" TrackerWatcherCommand::TrackerWatcherCommand(int cuid, - TorrentDownloadEngine* e): - Command(cuid), e(e) { + TorrentDownloadEngine* e, + const BtContextHandle& btContext): + BtContextAwareCommand(cuid, btContext), e(e) +{ } TrackerWatcherCommand::~TrackerWatcherCommand() {} bool TrackerWatcherCommand::execute() { - if(e->torrentMan->isHalt() && - e->segmentMan->errors > 0 && e->torrentMan->isAllAnnounceFailed() || - e->torrentMan->noMoreAnnounce()) { + if(btRuntime->isHalt() && + e->segmentMan->errors > 0 && btAnnounce->isAllAnnounceFailed() || + btAnnounce->noMoreAnnounce()) { return true; } Command* command = createCommand(); @@ -62,18 +64,18 @@ bool TrackerWatcherCommand::execute() { Command* TrackerWatcherCommand::createCommand() { Command* command = 0; - if(e->torrentMan->isAnnounceReady()) { - command = createRequestCommand(e->torrentMan->getAnnounceUrl()); - e->torrentMan->announceStart(); // inside it, trackers++. + if(btAnnounce->isAnnounceReady()) { + command = createRequestCommand(btAnnounce->getAnnounceUrl()); + btAnnounce->announceStart(); // inside it, trackers++. } else if(e->segmentMan->errors > 0) { - e->torrentMan->announceFailure(); // inside it, trackers = 0. + btAnnounce->announceFailure(); // inside it, trackers = 0. e->segmentMan->init(); - if(e->torrentMan->isAllAnnounceFailed()) { - e->torrentMan->resetAnnounce(); + if(btAnnounce->isAllAnnounceFailed()) { + btAnnounce->resetAnnounce(); // sleep a few seconds. command = new SleepCommand(cuid, e, - createRequestCommand(e->torrentMan->getAnnounceUrl()), + createRequestCommand(btAnnounce->getAnnounceUrl()), e->option->getAsInt(PREF_RETRY_WAIT)); } } @@ -84,7 +86,8 @@ Command* TrackerWatcherCommand::createRequestCommand(const string& url) { RequestHandle req; req->setUrl(url); req->isTorrent = true; - Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(e->torrentMan->getNewCuid(), req, e); + Command* command = + InitiateConnectionCommandFactory::createInitiateConnectionCommand(btRuntime->getNewCuid(), req, e); logger->info("CUID#%d - Creating new tracker request command #%d", cuid, command->getCuid()); return command; diff --git a/src/TrackerWatcherCommand.h b/src/TrackerWatcherCommand.h index 17708d1f..785fa7c3 100644 --- a/src/TrackerWatcherCommand.h +++ b/src/TrackerWatcherCommand.h @@ -35,10 +35,10 @@ #ifndef _D_TRACKER_WATCHER_COMMAND_H_ #define _D_TRACKER_WATCHER_COMMAND_H_ -#include "Command.h" +#include "BtContextAwareCommand.h" #include "TorrentDownloadEngine.h" -class TrackerWatcherCommand : public Command { +class TrackerWatcherCommand : public BtContextAwareCommand { private: TorrentDownloadEngine* e; @@ -48,7 +48,10 @@ private: */ Command* createRequestCommand(const string& url); public: - TrackerWatcherCommand(int cuid, TorrentDownloadEngine* e); + TrackerWatcherCommand(int cuid, + TorrentDownloadEngine* e, + const BtContextHandle& btContext); + ~TrackerWatcherCommand(); Command* createCommand(); diff --git a/src/Util.cc b/src/Util.cc index ef2aafd7..ffc38a2a 100644 --- a/src/Util.cc +++ b/src/Util.cc @@ -117,20 +117,28 @@ int Util::difftvsec(struct timeval tv1, struct timeval tv2) { return tv1.tv_sec-tv2.tv_sec; } -void Util::slice(Strings& result, const string& src, char delim) { +void Util::slice(Strings& result, const string& src, char delim, bool doTrim) { string::size_type p = 0; while(1) { string::size_type np = src.find(delim, p); if(np == string::npos) { - string term = trim(src.substr(p)); - if(term.size() > 0) { + string term = src.substr(p); + if(doTrim) { + term = trim(term); + } + if(term.size()) { result.push_back(term); } break; } string term = src.substr(p, np-p); + if(doTrim) { + term = trim(term); + } p = np+1; - result.push_back(trim(term)); + if(term.size()) { + result.push_back(term); + } } } @@ -65,7 +65,7 @@ public: * Take a string src which is a deliminated list and add its elements * into result. result is not cleared before conversion begins. */ - static void slice(Strings& result, const string& src, char delim); + static void slice(Strings& result, const string& src, char delim, bool trim = false); static string trim(const string& src); diff --git a/src/common.h b/src/common.h index 2013fdf3..15ebb043 100644 --- a/src/common.h +++ b/src/common.h @@ -71,6 +71,8 @@ public: } }; +#include "SharedHandle.h" + typedef deque<string> Strings; typedef deque<int> Integers; diff --git a/src/main.cc b/src/main.cc index ca4344c3..a14362a1 100644 --- a/src/main.cc +++ b/src/main.cc @@ -105,7 +105,7 @@ void showVersion() { "along with this program; if not, write to the Free Software\n" "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n"); cout << endl; - printf(_("Contact Info: %s\n"), "Tasuhiro Tsujikawa <tujikawa at users dot sourceforge dot net>"); + printf(_("Contact Info: %s\n"), "Tatsuhiro Tsujikawa <tujikawa at users dot sourceforge dot net>"); cout << endl; } |
