File indexing completed on 2024-11-24 04:31:14

0001 /*
0002     SPDX-FileCopyrightText: 2005 Joris Guisson <joris.guisson@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 #ifndef BTCACHEFILE_H
0007 #define BTCACHEFILE_H
0008 
0009 #include <QFile>
0010 #include <QMap>
0011 #include <QRecursiveMutex>
0012 #include <QSharedPointer>
0013 #include <util/constants.h>
0014 
0015 namespace bt
0016 {
0017 class PreallocationThread;
0018 
0019 /**
0020  * Interface which classes must implement to be able to map something from a CacheFile
0021  * It will also be used to notify when things get unmapped or remapped
0022  */
0023 class MMappeable
0024 {
0025 public:
0026     virtual ~MMappeable()
0027     {
0028     }
0029 
0030     /**
0031      * When a CacheFile is closed, this will be called on all existing mappings.
0032      */
0033     virtual void unmapped() = 0;
0034 };
0035 
0036 /**
0037     @author Joris Guisson <joris.guisson@gmail.com>
0038 
0039     Used by Single and MultiFileCache to write to disk.
0040 */
0041 class CacheFile : public QObject
0042 {
0043     Q_OBJECT
0044 public:
0045     CacheFile();
0046     ~CacheFile() override;
0047 
0048     enum Mode {
0049         READ,
0050         WRITE,
0051         RW,
0052     };
0053 
0054     /**
0055      * Open the file.
0056      * @param path Path of the file
0057      * @param size Max size of the file
0058      * @throw Error when something goes wrong
0059      */
0060     void open(const QString &path, Uint64 size);
0061 
0062     /// Change the path of the file
0063     void changePath(const QString &npath);
0064 
0065     /**
0066      * Map a part of the file into memory, will expand the file
0067      * if it is to small, but will not go past the limit set in open.
0068      * @param thing The thing that wishes to map the mmapping
0069      * @param off Offset into the file
0070      * @param size Size of the region to map
0071      * @param mode How the region will be mapped
0072      * @return A ptr to the mmaped region, or 0 if something goes wrong
0073      */
0074     void *map(MMappeable *thing, Uint64 off, Uint32 size, Mode mode);
0075 
0076     /**
0077      * Unmap a previously mapped region.
0078      * @param ptr Ptr to the region
0079      * @param size Size of the region
0080      */
0081     void unmap(void *ptr, Uint32 size);
0082 
0083     /**
0084      * Close the file, everything will be unmapped.
0085      * @param to_be_reopened Indicates if the close is temporarely (i.e. it will be reopened)
0086      */
0087     void close();
0088 
0089     /**
0090      * Read from the file.
0091      * @param buf Buffer to store data
0092      * @param size Size to read
0093      * @param off Offset to read from in file
0094      */
0095     void read(Uint8 *buf, Uint32 size, Uint64 off);
0096 
0097     /**
0098      * Write to the file.
0099      * @param buf Buffer to write
0100      * @param size Size to read
0101      * @param off Offset to read from in file
0102      */
0103     void write(const Uint8 *buf, Uint32 size, Uint64 off);
0104 
0105     /**
0106      * Preallocate disk space
0107      */
0108     void preallocate(PreallocationThread *prealloc);
0109 
0110     /// Get the number of bytes this cache file is taking up
0111     Uint64 diskUsage();
0112 
0113     typedef QSharedPointer<CacheFile> Ptr;
0114 
0115 private:
0116     void growFile(Uint64 to_write);
0117     void closeTemporary();
0118     void openFile(Mode mode);
0119     void unmapAll();
0120     bool allocateBytes(bt::Uint64 off, bt::Uint64 size);
0121 
0122 private Q_SLOTS:
0123     void aboutToClose();
0124 
0125 private:
0126     QFile *fptr;
0127     bool read_only;
0128     Uint64 max_size, file_size;
0129     QString path;
0130     struct Entry {
0131         MMappeable *thing;
0132         void *ptr;
0133         Uint32 size;
0134         Uint64 offset;
0135         Uint32 diff;
0136         Mode mode;
0137     };
0138     QMap<void *, Entry> mappings; // mappings where offset wasn't a multiple of 4K
0139     mutable QRecursiveMutex mutex;
0140     bool manual_close;
0141 };
0142 
0143 }
0144 
0145 #endif