1 | /* |
2 | This software is a contribution of the LiMux project of the city of Munich. |
3 | SPDX-FileCopyrightText: 2021 Robert Hoffmann <robert@roberthoffmann.de> |
4 | |
5 | SPDX-License-Identifier: LGPL-2.0-or-later |
6 | */ |
7 | #ifndef KNETWORKMOUNTS_H |
8 | #define KNETWORKMOUNTS_H |
9 | |
10 | #include <memory> |
11 | |
12 | #include <QObject> |
13 | #include <kcoreaddons_export.h> |
14 | |
15 | /*! |
16 | * \class KNetworkMounts |
17 | * \inmodule KCoreAddons |
18 | * |
19 | * Performance control on network mounts. |
20 | * |
21 | * This class provides methods for deciding whether operations |
22 | * on slow network mounts should be performed or not. |
23 | * |
24 | * Configuration is read from a configuration file network_mounts in |
25 | * the user's QStandardPaths::ConfigLocation. This file can be filled by using |
26 | * the network mounts performance configuration module or directly via setEnabled, |
27 | * setPaths, addPath and setOption |
28 | * \code |
29 | * KNetworkMounts::self()->setEnabled(true); |
30 | * KNetworkMounts::self()->setOption(KNetworkMounts::LowSideEffectsOptimizations, true); |
31 | * KNetworkMounts::self()->addPath(path1, KNetworkMounts::NfsPaths); |
32 | * KNetworkMounts::self()->addPath(path2, KNetworkMounts::NfsPaths); |
33 | * KNetworkMounts::self()->setPaths(listOfPaths, KNetworkMounts::SmbPaths); |
34 | * \endcode |
35 | * |
36 | * Use KNetworkMounts like this to check if the given url is on a |
37 | * configured slow path and the KNetworkMountOption LowSideEffectsOptimizations |
38 | * is enabled: |
39 | * \code |
40 | * if (KNetworkMounts::self()->isOptionEnabledForPath(url.toLocalFile(), |
41 | * KNetworkMounts::LowSideEffectsOptimizations)) |
42 | * { |
43 | * // skip operations which are slow on the given url if |
44 | * // KNetworkMountOption LowSideEffectsOptimizations is enabled |
45 | * } else { |
46 | * // given url is not configured being slow or the KNetworkMountOption |
47 | * // LowSideEffectsOptimizations is not enabled |
48 | * } |
49 | * \endcode |
50 | * |
51 | * If called for the first time, this creates a singleton instance and reads |
52 | * the config file. Subsequent calls just use this instance without reading |
53 | * the config file again. |
54 | * |
55 | * \since 5.85 |
56 | **/ |
57 | class KCOREADDONS_EXPORT KNetworkMounts : public QObject |
58 | { |
59 | Q_OBJECT |
60 | |
61 | public: |
62 | /*! |
63 | * Returns (and creates if necessary) the singleton instance |
64 | */ |
65 | static KNetworkMounts *self(); |
66 | |
67 | /*! |
68 | * The KNetworkMountOption enum |
69 | * |
70 | * \value LowSideEffectsOptimizations |
71 | * Don't run KDiskFreeSpaceInfo if slow path. |
72 | * Don't check for manually mounted drives. |
73 | * Don't check with QFileInfo::isWritable if it is writable, if not yet known, return true. |
74 | * Don't check with QFileInfo::isReadable if it is readable, return false. |
75 | * Don't check for desktop files just return false. |
76 | * Ignore .hidden files on slow paths. |
77 | * Don't read mime comment from .desktop or .directory files. |
78 | * Don't get the size with QFileInfo::size, just return 0, if not yet known. |
79 | * Don't determine mime type from file content, use file extension. |
80 | * Don't check for desktop files just return false. |
81 | * Don't call KFileSystemType::fileSystemType to check if the filesystem is slow, just return true. |
82 | * Don't count files/directories in subdirectories. |
83 | * Don't calculate sizes of subdirectories. |
84 | * Avoid check for dir at Kate startup. |
85 | * \value MediumSideEffectsOptimizations |
86 | * Don't return project for dir, avoid QFileInfo().absoluteDir(). |
87 | * Don't search for .kateconfig recursively |
88 | * Ignore recent files on slow paths |
89 | * \value StrongSideEffectsOptimizations |
90 | * Turn off symbolic link resolution |
91 | * \value KDirWatchDontAddWatches |
92 | * Disables dir watching completely for slow paths, avoids stat() calls on added dirs and subdirs |
93 | * \value SymlinkPathsUseCache |
94 | * Cache resolved symlink paths |
95 | */ |
96 | enum KNetworkMountOption { |
97 | LowSideEffectsOptimizations, |
98 | MediumSideEffectsOptimizations, |
99 | StrongSideEffectsOptimizations, |
100 | KDirWatchDontAddWatches, |
101 | SymlinkPathsUseCache |
102 | }; |
103 | Q_ENUM(KNetworkMountOption) |
104 | |
105 | /*! |
106 | * The KNetworkMountsType enum |
107 | * |
108 | * \value NfsPaths NFS paths |
109 | * \value SmbPaths SMB paths |
110 | * \value SymlinkDirectory Paths to directories which contain symbolic links to network mounts |
111 | * \value SymlinkToNetworkMount Paths which are symbolic links to network mounts |
112 | * \value Any Any slow path type. Do not use with setPaths or addPath |
113 | */ |
114 | enum KNetworkMountsType { NfsPaths, SmbPaths, SymlinkDirectory, SymlinkToNetworkMount, Any }; |
115 | Q_ENUM(KNetworkMountsType) |
116 | |
117 | /*! |
118 | * Query if \a path is configured to be a slow path of type \a type |
119 | * |
120 | * \a path the path to query |
121 | * |
122 | * \a type the type to query. If omitted, any type matches |
123 | * |
124 | * Returns \c true if \a path is a configured slow path of type \a type |
125 | * |
126 | * This function is also used to determine the filesystem type in KFileSystemType::fileSystemType |
127 | * (KFileSystemType::Smb or KFileSystemType::Nfs) without an expensive call to stafs(). For this |
128 | * to work the types of paths need to be correctly assigned in setPath or addPath |
129 | */ |
130 | bool isSlowPath(const QString &path, KNetworkMountsType type = Any); |
131 | |
132 | /*! |
133 | * Query if \a path is configured to be a slow path and \a option is enabled |
134 | * |
135 | * \a path the path to query |
136 | * |
137 | * \a option the option to query |
138 | * |
139 | * Returns \c true if \a path is a configured slow path and option \a option is enabled |
140 | */ |
141 | bool isOptionEnabledForPath(const QString &path, KNetworkMountOption option); |
142 | |
143 | /*! |
144 | * Query if the performance optimizations are switched on |
145 | * |
146 | * Returns \c true if on, \c false otherwise |
147 | */ |
148 | bool isEnabled() const; |
149 | |
150 | /*! |
151 | * Switch the performance optimizations on or off |
152 | * |
153 | * \a value the value to set |
154 | */ |
155 | void setEnabled(bool value); |
156 | |
157 | /*! |
158 | * Query a performance option |
159 | * |
160 | * \a option the option to query |
161 | * |
162 | * \a defaultValue the value to return if the option is not configured |
163 | * |
164 | * Returns \c true if option is on, \c false if not |
165 | * \sa KNetworkMountOption |
166 | */ |
167 | bool isOptionEnabled(const KNetworkMountOption option, const bool defaultValue = false) const; |
168 | |
169 | /*! |
170 | * Switch a performance option on or off |
171 | * |
172 | * \a option the option to change |
173 | * |
174 | * \a value the value to set |
175 | * |
176 | * \sa KNetworkMountOption |
177 | */ |
178 | void setOption(const KNetworkMountOption option, const bool value); |
179 | |
180 | /*! |
181 | * Query the configured paths for which optimizations are to take place |
182 | * |
183 | * Returns a list of paths |
184 | */ |
185 | QStringList paths(KNetworkMountsType type = Any) const; |
186 | |
187 | /*! |
188 | * Set the paths for which optimizations are to take place |
189 | * |
190 | * \a paths the paths to set |
191 | * |
192 | * \a type the type of paths. Do not use Any |
193 | * |
194 | * \sa KNetworkMountsType |
195 | */ |
196 | void setPaths(const QStringList &paths, KNetworkMountsType type); |
197 | |
198 | /*! |
199 | * Add a path for which optimizations are to take place |
200 | * |
201 | * \a path the path to add |
202 | * |
203 | * \a type the type of the path. Do not use Any |
204 | * |
205 | * \sa KNetworkMountsType |
206 | */ |
207 | void addPath(const QString &path, KNetworkMountsType type); |
208 | |
209 | /*! |
210 | * Resolves a \a path that may contain symbolic links to mounted network shares. |
211 | * |
212 | * A symlink path is either a directory which contains symbolic links to slow network mounts |
213 | * (SymlinkDirectory) or a direct symbolic link to a slow network mount ( * SymlinkToNfsOrSmbPaths). |
214 | * |
215 | * Example: |
216 | * There are some Samba shares mounted below /mnt. These are paths of type SmbPaths |
217 | * \code |
218 | * /mnt/server1/share1 |
219 | * /mnt/server1/share2 |
220 | * /mnt/server2/share3 |
221 | * \endcode |
222 | * |
223 | * A (logged in) user may have symbolic links to them in his home directory below netshares. The |
224 | * directory /home/user/netshares is a SymlinkDirectory: |
225 | * \code |
226 | * /home/user/netshares/share1 -> /mnt/server1/share1 |
227 | * /home/user/netshares/share2 -> /mnt/server1/share2 |
228 | * /home/user/netshares/share3 -> /mnt/server2/share3 |
229 | * \endcode |
230 | * |
231 | * There is a direct symbolic link from /home/user/share1 to /mnt/server1/share1. This is of type |
232 | * SymlinkToNfsOrSmbPaths: |
233 | * \code |
234 | * /home/user/share1 -> /mnt/server1/share1 |
235 | * \endcode |
236 | * |
237 | * Both types of symbolic links from symlink paths to the real mounted shares are resolved even if |
238 | * KNetworkMountOption StrongSideEffectsOptimizations is enabled. |
239 | * |
240 | * If the setup is like above a \a path |
241 | * \code |
242 | * /home/user/netshares/share1/Documents/file.txt |
243 | * \endcode |
244 | * |
245 | * would be resolved to |
246 | * \code |
247 | * /mnt/server1/share1/Documents/file.txt |
248 | * \endcode |
249 | * |
250 | * and a \a path |
251 | * \code |
252 | * /home/user/share1/Documents/file.txt |
253 | * \endcode |
254 | * |
255 | * would also be resolved to |
256 | * \code |
257 | * /mnt/server1/share1/Documents/file.txt |
258 | * \endcode |
259 | * |
260 | * Resolved paths are cached in a hash. |
261 | * |
262 | * \a path the path to resolve |
263 | * |
264 | * Returns the resolved path or \a path if \a path is not a symlink path or no symlink found |
265 | * \sa KNetworkMountsType |
266 | * \sa clearCache |
267 | * \sa isSlowPath |
268 | */ |
269 | QString canonicalSymlinkPath(const QString &path); |
270 | |
271 | /*! |
272 | * Clears the canonical symlink path cache |
273 | * |
274 | * Call this if directory structures on mounted network drives changed. Don't enable the |
275 | * cache (SymlinkPathsUseCache) if this happens often and the drives are usually accessed |
276 | * via the symlinks. This method exists mainly for the KCM. |
277 | * \sa canonicalSymlinkPath |
278 | */ |
279 | void clearCache(); |
280 | |
281 | /*! |
282 | * Synchronizes to config file |
283 | * |
284 | * QSettings synchronization also takes place automatically at regular intervals and from |
285 | * QSettings destructor, see QSettings::sync() documentation. |
286 | * |
287 | * Calls QSettings::sync() |
288 | */ |
289 | void sync(); |
290 | |
291 | private: |
292 | /// Creates a new KNetworkMounts object |
293 | KCOREADDONS_NO_EXPORT KNetworkMounts(); |
294 | |
295 | /// Destructor |
296 | KCOREADDONS_NO_EXPORT ~KNetworkMounts() override; |
297 | |
298 | std::unique_ptr<class KNetworkMountsPrivate> const d; |
299 | }; |
300 | |
301 | #endif // KNETWORKMOUNTS_H |
302 | |