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 **/
57class KCOREADDONS_EXPORT KNetworkMounts : public QObject
58{
59 Q_OBJECT
60
61public:
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
291private:
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

source code of kcoreaddons/src/lib/io/knetworkmounts.h