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