data/PayloadCacheLimits.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <QMutex> | ||
| 4 | #include <QSqlDatabase> | ||
| 5 | #include <QString> | ||
| 6 | #include <functional> | ||
| 7 | #include <memory> | ||
| 8 | |||
| 9 | // Payload (body + attachment BLOB) cache budget, folder purges and the | ||
| 10 | // folder statistics of the properties popup (Sprint 91 S91.2.4, extracted | ||
| 11 | // from MailCache). Callers reach it as `cache.payloadLimits()`. | ||
| 12 | // | ||
| 13 | // Plain class, no connection of its own: it uses the owning MailCache's | ||
| 14 | // QSqlDatabase, lastError string and cross-connection write mutex on that | ||
| 15 | // cache's thread. It owns the payload byte count and limit (the single | ||
| 16 | // owner of m_payloadCacheBytes, S91.0.7). The "InTransaction" enforcement | ||
| 17 | // never starts a transaction (MailCache::storeBodyPayload and | ||
| 18 | // AttachmentStore::storeAttachments call it inside their unit); the other | ||
| 19 | // writers own their BEGIN IMMEDIATE unit as before. Folder id lookups, FTS | ||
| 20 | // re-indexing of an evicted body and the folderHeadersRemoved signal stay | ||
| 21 | // with MailCache and are reached through Deps. | ||
| 22 | class PayloadCacheLimits { | ||
| 23 | public: | ||
| 24 | struct Deps { | ||
| 25 | std::function<qint64(const QString &account, const QString &path)> findFolderId; | ||
| 26 | std::function<bool(qint64 rowId)> indexHeaderById; | ||
| 27 | std::function<void(qint64 folderId)> folderHeadersRemoved; | ||
| 28 | }; | ||
| 29 | PayloadCacheLimits(QSqlDatabase &db, QString &lastError, | ||
| 30 | const std::shared_ptr<QRecursiveMutex> &writeMutex, Deps deps); | ||
| 31 | |||
| 32 | // Delete all cached data (headers + bodies) for a folder. | ||
| 33 | void purgeFolder(qint64 folderId); | ||
| 34 | |||
| 35 | // F-63: same purge as part of the caller's BEGIN IMMEDIATE transaction | ||
| 36 | // (MailCache::setUidValidity owns the epoch transition unit). Returns | ||
| 37 | // false and leaves the rollback to the caller when the delete fails. | ||
| 38 | bool purgeFolderInTransaction(qint64 folderId); | ||
| 39 | |||
| 40 | // T-138: Path-based convenience overloads for FolderPropertiesDialog | ||
| 41 | int cachedHeaderCount(const QString &account, const QString &folderPath, | ||
| 42 | QString *error = nullptr); | ||
| 43 | int cachedBodyCount(const QString &account, const QString &folderPath); | ||
| 44 | void purgeFolderByPath(const QString &account, const QString &folderPath); | ||
| 45 | |||
| 46 | // T-286: Extended statistics for folder properties dialog | ||
| 47 | qint64 cachedDiskUsage(const QString &account, const QString &folderPath); | ||
| 48 | qint64 totalServerSize(const QString &account, const QString &folderPath); | ||
| 49 | qint64 averageMailSize(const QString &account, const QString &folderPath); | ||
| 50 | // F-64: returns false when any step failed (bodies and their search | ||
| 51 | // text clear together or not at all). | ||
| 52 | bool purgeBodyCache(const QString &account, const QString &folderPath); | ||
| 53 | |||
| 54 | qint64 calculatePayloadCacheSize() const; | ||
| 55 | // Recompute the payload byte count from the database (S91.0.7 seam). | ||
| 56 | void refreshPayloadCacheBytes(); | ||
| 57 | bool enforcePayloadCacheLimit(qint64 protectedHeaderId = -1, | ||
| 58 | qint64 reserveBytes = 0); | ||
| 59 | |||
| 60 | // Caller owns BEGIN IMMEDIATE and rolls back eviction with its payload write. | ||
| 61 | bool enforcePayloadCacheLimitInTransaction(qint64 protectedHeaderId, | ||
| 62 | qint64 reserveBytes); | ||
| 63 | |||
| 64 | // Budget contract (tests configure small limits through it). | ||
| 65 | 17 | qint64 payloadCacheBytes() const { return m_payloadCacheBytes; } | |
| 66 | qint64 payloadCacheLimitBytes() const { return m_payloadCacheLimitBytes; } | ||
| 67 | 13 | void setPayloadCacheLimitBytes(qint64 bytes) { m_payloadCacheLimitBytes = bytes; } | |
| 68 | |||
| 69 | private: | ||
| 70 | QSqlDatabase &m_db; // owned by MailCache | ||
| 71 | QString &m_lastError; // MailCache::lastError() | ||
| 72 | const std::shared_ptr<QRecursiveMutex> &m_writeMutex; // MailCache's, replaced on open() | ||
| 73 | Deps m_deps; | ||
| 74 | qint64 m_payloadCacheBytes = 0; | ||
| 75 | qint64 m_payloadCacheLimitBytes = 1024LL * 1024 * 1024; | ||
| 76 | }; | ||
| 77 |