File indexing completed on 2024-03-24 17:22:52

0001 /*
0002    SPDX-FileCopyrightText: 2019-2020 Fabian Vogt <fabian@ritter-vogt.de>
0003    SPDX-FileCopyrightText: 2019-2020 Alexander Saoutkin <a.saoutkin@gmail.com>
0004    SPDX-License-Identifier: GPL-3.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include <fuse_lowlevel.h>
0010 
0011 #include <functional>
0012 #include <vector>
0013 #include <chrono>
0014 
0015 #include <QObject>
0016 #include <QUrl>
0017 #include <QString>
0018 
0019 #include <KIO/FileJob>
0020 
0021 class KIOFuseNode {
0022 public:
0023     // Creates a new node. Make sure to set the node's m_stat.st_ino once inserted.
0024     KIOFuseNode(const fuse_ino_t parentIno, const QString &nodeName, const struct stat &stat) :
0025         m_parentIno(parentIno),
0026         m_nodeName(nodeName),
0027         m_stat(stat)
0028     {}
0029 
0030     virtual ~KIOFuseNode() {}
0031 
0032     uint64_t m_lookupCount = 0, // This counts how many references to this node the kernel has
0033              m_openCount = 0; // This counts how often the kernel has this node opened
0034     fuse_ino_t m_parentIno;
0035     QString m_nodeName;
0036     // TODO: nlink of directories (./..)?
0037     struct stat m_stat;
0038 };
0039 
0040 // Base class for all nodes representing a directory
0041 class KIOFuseDirNode : public KIOFuseNode {
0042 public:
0043     using KIOFuseNode::KIOFuseNode;
0044     std::vector<fuse_ino_t> m_childrenInos;
0045 };
0046 
0047 // Used for automated testing of expiration.
0048 // Set by KIOFuseServicePrivate::forceNodeTimeout.
0049 extern std::chrono::steady_clock::time_point g_timeoutEpoch;
0050 
0051 class KIOFuseRemoteNodeInfo : public QObject {
0052     Q_OBJECT
0053 public:
0054     // Timeout for refreshing of attributes
0055     static const std::chrono::steady_clock::duration ATTR_TIMEOUT;
0056     // Override the URL
0057     QUrl m_overrideUrl;
0058     // Whether a stat was requested. If true, the signal "statRefreshed" will
0059     // be emitted on finish.
0060     bool m_statRequested = false;
0061     // Stores the last time a node's m_stat field was refreshed via KIO::stat or a parent's KIO::listDir.
0062     std::chrono::steady_clock::time_point m_lastStatRefresh = std::chrono::steady_clock::now();
0063     // Returns true if a node is due for a stat refresh, false otherwise.
0064     bool hasStatTimedOut() { return m_lastStatRefresh < g_timeoutEpoch || (std::chrono::steady_clock::now() - m_lastStatRefresh) >= ATTR_TIMEOUT; }
0065 Q_SIGNALS:
0066     // Emitted after finishing (successful or not) a attr refresh on this node
0067     void statRefreshed(int error);
0068 };
0069 
0070 class KIOFuseRemoteDirNode : public KIOFuseRemoteNodeInfo, public KIOFuseDirNode {
0071     Q_OBJECT
0072 public:
0073     using KIOFuseDirNode::KIOFuseDirNode;
0074 
0075     // Whether a dirlist was requested. If true, the signal "gotChildren" will
0076     // be emitted on finish.
0077     bool m_childrenRequested = false;
0078     // Stores the last time a node's children were refreshed via KIO::listDir.
0079     std::chrono::steady_clock::time_point m_lastChildrenRefresh = decltype(m_lastChildrenRefresh)::min();
0080     // Returns true if a node is due for a readdir refresh, false otherwise.
0081     bool haveChildrenTimedOut() { return m_lastChildrenRefresh < g_timeoutEpoch || (std::chrono::steady_clock::now() - m_lastChildrenRefresh) >= ATTR_TIMEOUT; }
0082 
0083 Q_SIGNALS:
0084     // Emitted after finishing (successful or not) a distlist on this node
0085     void gotChildren(int error);
0086 };
0087 
0088 class KIOFuseRemoteFileNode : public KIOFuseRemoteNodeInfo, public KIOFuseNode {
0089 public:
0090     using KIOFuseNode::KIOFuseNode;
0091 };
0092 
0093 class KIOFuseRemoteCacheBasedFileNode : public KIOFuseRemoteFileNode {
0094     Q_OBJECT
0095 public:
0096     using KIOFuseRemoteFileNode::KIOFuseRemoteFileNode;
0097     ~KIOFuseRemoteCacheBasedFileNode() {
0098         if(m_localCache)
0099             fclose(m_localCache);
0100     }
0101     // Cache information
0102     bool cacheIsComplete() { return m_cacheComplete; }
0103     FILE *m_localCache = nullptr; // The tmpfile containing data. If nullptr, not requested yet.
0104     off_t m_cacheSize = 0; // Size of the local cache - might be less than m_stat.st_size.
0105     bool m_cacheComplete = false,
0106          m_cacheDirty = false, // Set on every write to m_localCache, cleared when a flush starts
0107          m_flushRunning = false; // If a flush is currently running
0108     int m_numKilledJobs = 0; // reset on successful flush, incremented every time job is killed because cache is dirty (among other factors)
0109 Q_SIGNALS:
0110     // Emitted when a download operation on this node made progress, finished or failed.
0111     void localCacheChanged(int error);
0112     // Emitted after finishing (successful or not) a cache flush on this node
0113     void cacheFlushed(int error);
0114 };
0115 
0116 class KIOFuseRemoteFileJobBasedFileNode : public KIOFuseRemoteFileNode {
0117 public:
0118     using KIOFuseRemoteFileNode::KIOFuseRemoteFileNode;
0119 };
0120 
0121 class KIOFuseSymLinkNode : public KIOFuseRemoteNodeInfo, public KIOFuseNode {
0122 public:
0123     using KIOFuseNode::KIOFuseNode;
0124     QString m_target;
0125 };