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 <KCoreAddons/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 KDirWatchUseINotify, ///< Use Inotify on the path (instead of FAM on NFS mounts). Inotify detects changes only locally, FAM works also remotely with NFS 95 KDirWatchDontAddWatches, ///< Disables dir watching completely for slow paths, avoids stat() calls on added dirs and subdirs 96 SymlinkPathsUseCache ///< Cache resolved symlink paths 97 }; 98 Q_ENUM(KNetworkMountOption) 99 100 /** 101 * The KNetworkMountsType enum 102 */ 103 enum KNetworkMountsType { 104 NfsPaths, ///< NFS paths 105 SmbPaths, ///< SMB paths 106 SymlinkDirectory, ///< Paths to directories which contain symbolic links to network mounts 107 SymlinkToNetworkMount, ///< Paths which are symbolic links to network mounts 108 Any ///< Any slow path type. Do not use with @ref setPaths or @ref addPath 109 }; 110 Q_ENUM(KNetworkMountsType) 111 112 /** 113 * Query if @p path is configured to be a slow path of type @p type 114 * 115 * @param path the path to query 116 * @param type the type to query. If omitted, any type matches 117 * @return @c true if @p path is a configured slow path of type @p type 118 * 119 * This function is also used to determine the filesystem type in @ref KFileSystemType::fileSystemType 120 * (KFileSystemType::Smb or KFileSystemType::Nfs) without an expensive call to stafs(). For this 121 * to work the types of paths need to be correctly assigned in @ref setPath or @ref addPath 122 */ 123 bool isSlowPath(const QString &path, KNetworkMountsType type = Any); 124 125 /** 126 * Query if @p path is configured to be a slow path and @p option is enabled 127 * 128 * @param path the path to query 129 * @param option the option to query 130 * @return @c true if @p path is a configured slow path and option @p option is enabled 131 */ 132 bool isOptionEnabledForPath(const QString &path, KNetworkMountOption option); 133 134 /** 135 * Query if the performance optimizations are switched on 136 * 137 * @return @c true if on, @c false otherwise 138 */ 139 bool isEnabled() const; 140 141 /** 142 * Switch the performance optimizations on or off 143 * 144 * @param value the value to set 145 */ 146 void setEnabled(bool value); 147 148 /** 149 * Query a performance option 150 * 151 * @param option the option to query 152 * @param defaultValue the value to return if the option is not configured 153 * @return @c true if option is on, @c false if not 154 * @see KNetworkMountOption 155 */ 156 bool isOptionEnabled(const KNetworkMountOption option, const bool defaultValue = false) const; 157 158 /** 159 * Switch a performance option on or off 160 * 161 * @param option the option to change 162 * @param value the value to set 163 * @see KNetworkMountOption 164 */ 165 void setOption(const KNetworkMountOption option, const bool value); 166 167 /** 168 * Query the configured paths for which optimizations are to take place 169 * 170 * @return a list of paths 171 */ 172 QStringList paths(KNetworkMountsType type = Any) const; 173 174 /** 175 * Set the paths for which optimizations are to take place 176 * 177 * @param paths the paths to set 178 * @param type the type of paths. Do not use @ref Any 179 * @see KNetworkMountsType 180 */ 181 void setPaths(const QStringList &paths, KNetworkMountsType type); 182 183 /** 184 * Add a path for which optimizations are to take place 185 * 186 * @param path the path to add 187 * @param type the type of the path. Do not use @ref Any 188 * @see KNetworkMountsType 189 */ 190 void addPath(const QString &path, KNetworkMountsType type); 191 192 /** 193 * Resolves a @p path that may contain symbolic links to mounted network shares. 194 * 195 * A symlink path is either a directory which contains symbolic links to slow network mounts 196 * (@ref SymlinkDirectory) or a direct symbolic link to a slow network mount (@ref 197 * SymlinkToNfsOrSmbPaths). 198 * 199 * Example: 200 * There are some Samba shares mounted below /mnt. These are @ref paths of type @ref SmbPaths 201 * @code 202 * /mnt/server1/share1 203 * /mnt/server1/share2 204 * /mnt/server2/share3 205 * @endcode 206 * 207 * A (logged in) user may have symbolic links to them in his home directory below netshares. The 208 * directory /home/user/netshares is a @ref SymlinkDirectory: 209 * @code 210 * /home/user/netshares/share1 -> /mnt/server1/share1 211 * /home/user/netshares/share2 -> /mnt/server1/share2 212 * /home/user/netshares/share3 -> /mnt/server2/share3 213 * @endcode 214 * 215 * There is a direct symbolic link from /home/user/share1 to /mnt/server1/share1. This is of type 216 * @ref SymlinkToNfsOrSmbPaths: 217 * @code 218 * /home/user/share1 -> /mnt/server1/share1 219 * @endcode 220 * 221 * Both types of symbolic links from symlink paths to the real mounted shares are resolved even if 222 * KNetworkMountOption @ref StrongSideEffectsOptimizations is enabled. 223 224 * If the setup is like above a @p path 225 * @code 226 * /home/user/netshares/share1/Documents/file.txt 227 * @endcode 228 * 229 * would be resolved to 230 * @code 231 * /mnt/server1/share1/Documents/file.txt 232 * @endcode 233 * 234 * and a @p path 235 * @code 236 * /home/user/share1/Documents/file.txt 237 * @endcode 238 * 239 * would also be resolved to 240 * @code 241 * /mnt/server1/share1/Documents/file.txt 242 * @endcode 243 * 244 * Resolved paths are cached in a hash. 245 * 246 * @param path the path to resolve 247 * @return the resolved path or @p path if @p path is not a symlink path or no symlink found 248 * @see KNetworkMountsType 249 * @see clearCache 250 * @see isSlowPath 251 */ 252 QString canonicalSymlinkPath(const QString &path); 253 254 /** 255 * Clears the canonical symlink path cache 256 * 257 * Call this if directory structures on mounted network drives changed. Don't enable the 258 * cache (@ref SymlinkPathsUseCache) if this happens often and the drives are usually accessed 259 * via the symlinks. This method exists mainly for the KCM. 260 * @see canonicalSymlinkPath 261 */ 262 void clearCache(); 263 264 /** 265 * Synchronizes to config file 266 * 267 * QSettings synchronization also takes place automatically at regular intervals and from 268 * QSettings destructor, see QSettings::sync() documentation. 269 * 270 * Calls QSettings::sync() 271 */ 272 void sync(); 273 274 private: 275 /// Creates a new KNetworkMounts object 276 KNetworkMounts(); 277 278 /// Destructor 279 ~KNetworkMounts() override; 280 281 std::unique_ptr<class KNetworkMountsPrivate> const d; 282 }; 283 284 #endif // KNETWORKMOUNTS_H 285