diff options
Diffstat (limited to 'libktorrent/torrent/chunkmanager.h')
-rw-r--r-- | libktorrent/torrent/chunkmanager.h | 366 |
1 files changed, 366 insertions, 0 deletions
diff --git a/libktorrent/torrent/chunkmanager.h b/libktorrent/torrent/chunkmanager.h new file mode 100644 index 0000000..daa2300 --- /dev/null +++ b/libktorrent/torrent/chunkmanager.h @@ -0,0 +1,366 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@gmail.com * + * * + * 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. * + ***************************************************************************/ +#ifndef BTCHUNKMANAGER_H +#define BTCHUNKMANAGER_H + +#include <qmap.h> +#include <qstring.h> +#include <qobject.h> +#include <qptrvector.h> +#include <util/bitset.h> +#include "chunk.h" +#include "globals.h" + +class QStringList; + +namespace KIO +{ + class Job; +} + +namespace bt +{ + class Torrent; + class Cache; + class TorrentFile; + class PreallocationThread; + + struct NewChunkHeader + { + unsigned int index; // the Chunks index + unsigned int deprecated; // offset in cache file + }; + + /** + * @author Joris Guisson + * + * Manages all Chunk's and the cache file, where all the chunk's are stored. + * It also manages a separate index file, where the position of each piece + * in the cache file is stored. + * + * The chunks are stored in the cache file in the correct order. Eliminating + * the need for a file reconstruction algorithm for single files. + */ + class ChunkManager : public QObject + { + Q_OBJECT + + Torrent & tor; + QString index_file,file_info_file,file_priority_file; + QPtrVector<Chunk> chunks; + Cache* cache; + QMap<Uint32,TimeStamp> loaded; // loaded chunks and when they were loaded + BitSet bitset; + BitSet excluded_chunks; + BitSet only_seed_chunks; + BitSet todo; + mutable Uint32 chunks_left; + mutable bool recalc_chunks_left; + Uint32 corrupted_count; + Uint32 recheck_counter; + bool during_load; + public: + ChunkManager(Torrent & tor, + const QString & tmpdir, + const QString & datadir, + bool custom_output_name); + virtual ~ChunkManager(); + + /// Get the torrent + const Torrent & getTorrent() const {return tor;} + + /// Get the data dir + QString getDataDir() const; + + /// Get the actual output path + QString getOutputPath() const; + + void changeOutputPath(const QString& output_path); + + /// Remove obsolete chunks + void checkMemoryUsage(); + + /** + * Change the data dir. + * @param data_dir + */ + void changeDataDir(const QString & data_dir); + + /** + * Move the data files of the torrent. + * @param ndir The new directory + * @return The job doing the move + */ + KIO::Job* moveDataFiles(const QString & ndir); + + /** + * The move data files job has finished + * @param job The move job + */ + void moveDataFilesCompleted(KIO::Job* job); + + /** + * Loads the index file. + * @throw Error When it can be loaded + */ + void loadIndexFile(); + + /** + * Create the cache file, and index files. + * @param check_priority Make sure chunk priorities and dnd status of files match + * @throw Error When it can be created + */ + void createFiles(bool check_priority = false); + + /** + * Test all files and see if they are not missing. + * If so put them in a list + */ + bool hasMissingFiles(QStringList & sl); + + /** + * Preallocate diskspace for all files + * @param prealloc The thread doing the preallocation + */ + void preallocateDiskSpace(PreallocationThread* prealloc); + + /** + * Open the necessary files when the download gets started. + */ + void start(); + + /** + * Closes files when the download gets stopped. + */ + void stop(); + + /** + * Get's the i'th Chunk. + * @param i The Chunk's index + * @return The Chunk, or 0 when i is out of bounds + */ + Chunk* getChunk(unsigned int i); + + /** + * Get's the i'th Chunk. Makes sure that the Chunk's data + * is in memory. If the Chunk hasn't been downloaded yet 0 + * is returned. Whenever the Chunk needs to be uploaded, call + * this function. This changes the status to MMAPPED or BUFFERED. + * @param i The Chunk's index + * @return The Chunk, or 0 when i is out of bounds + */ + Chunk* grabChunk(unsigned int i); + + /** + * Prepare a chunk for downloading + * @param c The Chunk + * @param allways Always do this, even if the chunk is not NOT_DOWNLOADED + * @return true if ok, false if the chunk is not NOT_DOWNLOADED + */ + bool prepareChunk(Chunk* c,bool allways = false); + + /** + * The upload is done, and the Chunk is no longer needed. + * The Chunk's data might be cleared, if we are using up to much + * memory. + * @param i The Chunk's index + */ + void releaseChunk(unsigned int i); + + /** + * Reset a chunk as if it were never downloaded. + * @param i The chunk + */ + void resetChunk(unsigned int i); + + /** + * Save the i'th Chunk to the cache_file. + * Also changes the Chunk's status to ON_DISK. + * The Chunk's data is immediately cleared. + * @param i The Chunk's index + * @param update_index Update the index or not + */ + void saveChunk(unsigned int i,bool update_index = true); + + /** + * Calculates the number of bytes left for the tracker. Does include + * excluded chunks (this should be used for the tracker). + * @return The number of bytes to download + the number of bytes excluded + */ + Uint64 bytesLeft() const; + + /** + * Calculates the number of bytes left to download. + */ + Uint64 bytesLeftToDownload() const; + + /** + * Calculates the number of bytes which have been excluded. + * @return The number of bytes excluded + */ + Uint64 bytesExcluded() const; + + /** + * Calculates the number of chunks left to download. + * Does not include excluded chunks. + * @return The number of chunks to download + */ + Uint32 chunksLeft() const; + + /** + * Check if we have all chunks, this is not the same as + * chunksLeft() == 0, it does not look at excluded chunks. + * @return true if all chunks have been downloaded + */ + bool haveAllChunks() const; + + /** + * Get the number of chunks which have been excluded. + * @return The number of excluded chunks + */ + Uint32 chunksExcluded() const; + + /** + * Get the number of downloaded chunks + * @return + */ + Uint32 chunksDownloaded() const; + + /** + * Get the number of only seed chunks. + */ + Uint32 onlySeedChunks() const; + + /** + * Get a BitSet of the status of all Chunks + */ + const BitSet & getBitSet() const {return bitset;} + + /** + * Get the excluded bitset + */ + const BitSet & getExcludedBitSet() const {return excluded_chunks;} + + /** + * Get the only seed bitset. + */ + const BitSet & getOnlySeedBitSet() const {return only_seed_chunks;} + + /// Get the number of chunks into the file. + Uint32 getNumChunks() const {return chunks.count();} + + /// Print memory usage to log file + void debugPrintMemUsage(); + + /** + * Make sure that a range will get priority over other chunks. + * @param from First chunk in range + * @param to Last chunk in range + */ + void prioritise(Uint32 from,Uint32 to, Priority priority); + + /** + * Make sure that a range will not be downloaded. + * @param from First chunk in range + * @param to Last chunk in range + */ + void exclude(Uint32 from,Uint32 to); + + /** + * Make sure that a range will be downloaded. + * Does the opposite of exclude. + * @param from First chunk in range + * @param to Last chunk in range + */ + void include(Uint32 from,Uint32 to); + + + /** + * Data has been checked, and these chunks are OK. + * The ChunkManager will update it's internal structures + * @param ok_chunks The ok_chunks + */ + void dataChecked(const BitSet & ok_chunks); + + /// Test if the torrent has existing files, only works the first time a torrent is loaded + bool hasExistingFiles() const; + + /// Recreates missing files + void recreateMissingFiles(); + + /// Set missing files as do not download + void dndMissingFiles(); + + /// Delete all data files + void deleteDataFiles(); + + /// Are all not deselected chunks downloaded. + bool completed() const; + + /// Set the maximum chunk size for a data check, 0 means alllways check + static void setMaxChunkSizeForDataCheck(Uint32 mcs) {max_chunk_size_for_data_check = mcs;} + + /// Get the current disk usage of all the files in this torrent + Uint64 diskUsage(); + signals: + /** + * Emitted when a range of chunks has been excluded + * @param from First chunk in range + * @param to Last chunk in range + */ + void excluded(Uint32 from,Uint32 to); + + /** + * Emitted when a range of chunks has been included back. + * @param from First chunk in range + * @param to Last chunk in range + */ + void included(Uint32 from,Uint32 to); + + /** + * Emitted when chunks get excluded or included, so + * that the statistics can be updated. + */ + void updateStats(); + + /** + * A corrupted chunk has been found during uploading. + * @param chunk The chunk + */ + void corrupted(Uint32 chunk); + + private: + void saveIndexFile(); + void writeIndexFileEntry(Chunk* c); + void saveFileInfo(); + void loadFileInfo(); + void savePriorityInfo(); + void loadPriorityInfo(); + + private slots: + void downloadStatusChanged(TorrentFile* tf,bool download); + void downloadPriorityChanged(TorrentFile* tf,Priority newpriority,Priority oldpriority); + + static Uint32 max_chunk_size_for_data_check; + }; + +} + +#endif |