File indexing completed on 2024-12-01 13:48:42
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 };