1 /* 2 SPDX-FileCopyrightText: 2005 Joris Guisson <joris.guisson@gmail.com> 3 4 SPDX-License-Identifier: GPL-2.0-or-later 5 */ 6 #ifndef BTCACHE_H 7 #define BTCACHE_H 8 9 #include <QMultiMap> 10 #include <QSet> 11 #include <QString> 12 #include <diskio/piecedata.h> 13 #include <ktorrent_export.h> 14 #include <torrent/torrent.h> 15 #include <util/constants.h> 16 17 class QStringList; 18 19 namespace bt 20 { 21 class TorrentFile; 22 class Chunk; 23 class PreallocationThread; 24 class TorrentFileInterface; 25 class Job; 26 27 /** 28 * @author Joris Guisson 29 * @brief Manages the temporary data 30 * 31 * Interface for a class which manages downloaded data. 32 * Subclasses should implement the load and save methods. 33 */ 34 class KTORRENT_EXPORT Cache 35 { 36 public: 37 Cache(Torrent &tor, const QString &tmpdir, const QString &datadir); 38 virtual ~Cache(); 39 40 /** 41 * Load the file map of a torrent. 42 * If it doesn't exist, it needs to be created. 43 */ 44 virtual void loadFileMap() = 0; 45 46 /** 47 * Save the file map of a torrent 48 */ 49 virtual void saveFileMap() = 0; 50 51 /// Get the datadir 52 QString getDataDir() const 53 { 54 return datadir; 55 } 56 57 /** 58 * Get the actual output path. 59 * @return The output path 60 */ 61 virtual QString getOutputPath() const = 0; 62 63 /** 64 * Changes the tmp dir. All data files should already been moved. 65 * This just modifies the tmpdir variable. 66 * @param ndir The new tmpdir 67 */ 68 virtual void changeTmpDir(const QString &ndir); 69 70 /** 71 * Changes output path. All data files should already been moved. 72 * This just modifies the datadir variable. 73 * @param outputpath New output path 74 */ 75 virtual void changeOutputPath(const QString &outputpath) = 0; 76 77 /** 78 * Move the data files to a new directory. 79 * @param ndir The directory 80 * @return The job doing the move 81 */ 82 virtual Job *moveDataFiles(const QString &ndir) = 0; 83 84 /** 85 * A move of a bunch of data files has finished 86 * @param job The job doing the move 87 */ 88 virtual void moveDataFilesFinished(Job *job) = 0; 89 90 /** 91 * Load a piece into memory. If something goes wrong, 92 * an Error should be thrown. 93 * @param c The Chunk 94 * @param off The offset of the piece 95 * @param length The length of the piece 96 * @return Pointer to the data 97 */ 98 virtual PieceData::Ptr loadPiece(Chunk *c, Uint32 off, Uint32 length) = 0; 99 100 /** 101 * Prepare a piece for writing. If something goes wrong, 102 * an Error should be thrown. 103 * @param c The Chunk 104 * @param off The offset of the piece 105 * @param length The length of the piece 106 * @return Pointer to the data 107 */ 108 virtual PieceData::Ptr preparePiece(Chunk *c, Uint32 off, Uint32 length) = 0; 109 110 /** 111 * Save a piece to disk, will only actually save in buffered mode 112 * @param piece The piece 113 */ 114 virtual void savePiece(PieceData::Ptr piece) = 0; 115 116 /** 117 * Create all the data files to store the data. 118 */ 119 virtual void create() = 0; 120 121 /** 122 * Close the cache file(s). 123 */ 124 virtual void close() = 0; 125 126 /** 127 * Open the cache file(s) 128 */ 129 virtual void open() = 0; 130 131 /// Does nothing, can be overridden to be alerted of download status changes of a TorrentFile 132 virtual void downloadStatusChanged(TorrentFile *, bool){}; 133 134 /** 135 * Prepare disksapce preallocation 136 * @param prealloc The thread going to do the preallocation 137 */ 138 virtual void preparePreallocation(PreallocationThread *prealloc) = 0; 139 140 /// See if the download has existing files 141 bool hasExistingFiles() const 142 { 143 return preexisting_files; 144 } 145 146 /** 147 * Test all files and see if they are not missing. 148 * If so put them in a list 149 */ 150 virtual bool hasMissingFiles(QStringList &sl) = 0; 151 152 /** 153 * Delete all data files, in case of multi file torrents 154 * empty directories should also be deleted. 155 * @return The job doing the delete 156 */ 157 virtual Job *deleteDataFiles() = 0; 158 159 /** 160 * Move some files to a new location 161 * @param files Map of files to move and their new location 162 * @return Job The job doing the move 163 */ 164 virtual Job *moveDataFiles(const QMap<TorrentFileInterface *, QString> &files); 165 166 /** 167 * The job doing moveDataFiles (with the map parameter) has finished 168 * @param files The files map with all the moves 169 * @param job The job doing the move 170 */ 171 virtual void moveDataFilesFinished(const QMap<TorrentFileInterface *, QString> &files, Job *job); 172 173 /** 174 * See if we are allowed to use mmap, when loading chunks. 175 * This will return false if we are close to system limits. 176 */ 177 static bool mappedModeAllowed(); 178 179 /** 180 * Get the number of bytes all the files of this torrent are currently using on disk. 181 * */ 182 virtual Uint64 diskUsage() = 0; 183 184 /** 185 * Determine the mount points of all the files in this torrent 186 * @return bool True if we can, false if not 187 **/ 188 virtual bool getMountPoints(QSet<QString> &mps) = 0; 189 190 /** 191 * Enable or disable diskspace preallocation 192 * @param on 193 */ 194 static void setPreallocationEnabled(bool on) 195 { 196 preallocate_files = on; 197 } 198 199 /** 200 * Check if diskspace preallocation is enabled 201 * @return true if it is 202 */ 203 static bool preallocationEnabled() 204 { 205 return preallocate_files; 206 } 207 208 /** 209 * Enable or disable full diskspace preallocation 210 * @param on 211 */ 212 static void setPreallocateFully(bool on) 213 { 214 preallocate_fully = on; 215 } 216 217 /** 218 * Check if full diskspace preallocation is enabled. 219 * @return true if it is 220 */ 221 static bool preallocateFully() 222 { 223 return preallocate_fully; 224 } 225 226 /** 227 * Check memory usage and free all PieceData objects which are no longer needed. 228 */ 229 void checkMemoryUsage(); 230 231 /** 232 * Clear all pieces of a chunk 233 * @param c The chunk 234 * */ 235 void clearPieces(Chunk *c); 236 237 /** 238 * Load the mount points of this torrent 239 **/ 240 void loadMountPoints(); 241 242 /// Is the storage mounted ? 243 bool isStorageMounted(QStringList &missing); 244 245 protected: 246 PieceData::Ptr findPiece(Chunk *c, Uint32 off, Uint32 len, bool read_only); 247 void insertPiece(Chunk *c, PieceData::Ptr p); 248 void clearPieceCache(); 249 void cleanupPieceCache(); 250 void saveMountPoints(const QSet<QString> &mp); 251 252 protected: 253 Torrent &tor; 254 QString tmpdir; 255 QString datadir; 256 bool preexisting_files; 257 Uint32 mmap_failures; 258 259 typedef QMultiMap<Chunk *, PieceData::Ptr> PieceCache; 260 PieceCache piece_cache; 261 262 QSet<QString> mount_points; 263 264 private: 265 static bool preallocate_files; 266 static bool preallocate_fully; 267 }; 268 269 } 270 271 #endif 272