You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
367 lines
10 KiB
367 lines
10 KiB
15 years ago
|
/***************************************************************************
|
||
|
* 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
|