Avoid long "hanging" if Windows UNC path is not reachable

Use own "isDirExisting" function checking UNC paths
This commit is contained in:
Klaus Basan
2018-03-08 18:48:14 +01:00
parent 32196f5e8e
commit 42ef7c5633
8 changed files with 120 additions and 13 deletions

View File

@@ -203,8 +203,7 @@ namespace BlackCore
{
// ever used with XPlane
const QString pluginDir = CXPlaneUtil::pluginDirFromRootDir(m_simulatorSettings.getSimulatorDirectoryOrDefault(CSimulatorInfo::XPLANE));
const QDir dir(pluginDir);
if (dir.exists())
if (CDirectoryUtils::isDirExisting(pluginDir))
{
// only check if we are on a XP machine
const QStringList conflicts = CXPlaneUtil::findConflictingPlugins(pluginDir);

View File

@@ -479,7 +479,7 @@ namespace BlackCore
if (part2 == "show")
{
const QDir dir(CInterpolationLogger::getLogDirectory());
if (dir.exists())
if (CDirectoryUtils::isDirExisting(dir))
{
const QUrl dirUrl = QUrl::fromLocalFile(dir.absolutePath());
QDesktopServices::openUrl(dirUrl); // show dir in browser

View File

@@ -9,9 +9,9 @@
//! \cond PRIVATE
#include "blackmisc/directoryutils.h"
#include "blackmisc/fileutils.h"
#include "blackmisc/range.h"
#include "directoryutils.h"
#include "fileutils.h"
#include "range.h"
#include "blackconfig/buildconfig.h"
#include <QCoreApplication>
#include <QDir>
@@ -416,7 +416,7 @@ namespace BlackMisc
{
if (testDir.isEmpty()) { return false; }
const QDir dir(testDir);
if (!dir.exists()) { return false; }
if (!CDirectoryUtils::isDirExisting(dir)) { return false; }
return !dir.isEmpty();
}
@@ -438,6 +438,33 @@ namespace BlackMisc
return dirs;
}
bool CDirectoryUtils::isDirExisting(const QString &path)
{
if (!CBuildConfig::isRunningOnWindowsNtPlatform())
{
const QDir dir(path);
return dir.exists();
}
// Windows
if (!CFileUtils::isWindowsUncPath(path))
{
const QDir dir(path);
return dir.exists();
}
const QString machine(CFileUtils::windowsUncMachine(path));
if (!CFileUtils::canPingUncMachine(machine)) { return false; }
const QDir dir(path);
return dir.exists();
}
bool CDirectoryUtils::isDirExisting(const QDir &dir)
{
if (!CFileUtils::isWindowsUncPath(dir.absolutePath())) { return dir.exists(); }
return CDirectoryUtils::isDirExisting(dir.absolutePath());
}
QSet<QString> CDirectoryUtils::fileNamesToQSet(const QFileInfoList &fileInfoList)
{
QSet<QString> sl;

View File

@@ -18,6 +18,7 @@
#include <QSet>
#include <QString>
#include <QDateTime>
#include <QDir>
#include <QFileInfoList>
namespace BlackMisc
@@ -144,6 +145,14 @@ namespace BlackMisc
//! Get the existing directories
static QStringList getExistingUnemptyDirectories(const QStringList &directories);
//! Directory existing? Also checking UNC paths upfront.
//! \remark Motivation: if an UNC cannot be accessed (e.g. machine is down) it can take very long before functions like QDir respond
//! \remark for non-UNC paths it is the same as the QDir checks
//! @{
static bool isDirExisting(const QString &path);
static bool isDirExisting(const QDir &dir);
//! @}
//! Result of directory comparison
struct DirComparison
{

View File

@@ -7,9 +7,10 @@
* contained in the LICENSE file.
*/
#include "blackmisc/network/networkutils.h"
#include "blackmisc/math/mathutils.h"
#include "blackmisc/worker.h"
#include "blackmisc/fileutils.h"
#include "blackmisc/math/mathutils.h"
#include "blackconfig/buildconfig.h"
#include <QCoreApplication>
@@ -21,10 +22,12 @@
#include <QLockFile>
#include <QTextStream>
#include <QtGlobal>
#include <QMap>
#include <algorithm>
using namespace BlackConfig;
using namespace BlackMisc::Math;
using namespace BlackMisc::Network;
namespace BlackMisc
{
@@ -383,6 +386,59 @@ namespace BlackMisc
return fixedPaths;
}
bool CFileUtils::isWindowsUncPath(const QString &filePath)
{
if (filePath.startsWith("//") || filePath.startsWith("\\\\")) { return true; }
if (!CBuildConfig::isRunningOnWindowsNtPlatform()) { return false; } // "/tmp" is valid on Unix/Mac
// Windows here
const QString fp = fixWindowsUncPath(filePath);
return (fp.startsWith("//") || fp.startsWith("\\\\"));
}
QString CFileUtils::windowsUncMachine(const QString &filePath)
{
if (!CFileUtils::isWindowsUncPath(filePath)) { return QStringLiteral(""); }
QString f = filePath;
f.replace("\\", "/");
f.replace("//", "");
if (f.startsWith("/")) { f = f.mid(1); }
const int i = f.indexOf('/');
if (i < 0) { return f; }
return f.left(i);
}
bool CFileUtils::canPingUncMachine(const QString &machine)
{
static QMap<QString, qint64> good;
static QMap<QString, qint64> bad;
if (machine.isEmpty()) { return false; }
const QString m = machine.toLower();
if (good.contains(m)) { return true; } // good ones we only test once
if (bad.contains(m))
{
const qint64 ts = bad.value(m);
const qint64 dt = QDateTime::currentSecsSinceEpoch() - ts;
if (dt < 1000 * 60) { return false; } // still bad
// outdated, test again
}
const bool p = CNetworkUtils::canPing(m);
if (p)
{
good.insert(m, QDateTime::currentSecsSinceEpoch());
bad.remove(m);
}
else
{
bad.insert(m, QDateTime::currentSecsSinceEpoch());
good.remove(m);
}
return p;
}
QString CFileUtils::toWindowsLocalPath(const QString &path)
{
QString p = CFileUtils::fixWindowsUncPath(path);

View File

@@ -147,6 +147,15 @@ namespace BlackMisc
//! Fix UNC file paths
static QStringList fixWindowsUncPaths(const QStringList &filePaths);
//! Windows UNC path?
static bool isWindowsUncPath(const QString &filePath);
//! Machine in Windows UNC path
static QString windowsUncMachine(const QString &filePath);
//! Can connect the UNC machine
static bool canPingUncMachine(const QString &machine);
//! To Windows path using "\" delimiter
static QString toWindowsLocalPath(const QString &path);

View File

@@ -74,7 +74,14 @@ namespace BlackMisc
}
process.start();
process.waitForFinished();
return process.exitCode() == 0;
const int rc = process.exitCode();
if (rc != 0) { return false; }
const QString std = process.readAllStandardOutput();
const QString err = process.readAllStandardError();
if (std.contains("unreachable", Qt::CaseInsensitive)) { return false; }
if (err.contains("unreachable", Qt::CaseInsensitive)) { return false; }
return true;
}
bool CNetworkUtils::canPing(const CUrl &url)
@@ -92,7 +99,7 @@ namespace BlackMisc
if (address.isNull()) { continue; }
if (address.protocol() == QAbstractSocket::IPv4Protocol)
{
QString a = address.toString();
const QString a = address.toString();
ips.append(a);
}
}

View File

@@ -157,8 +157,8 @@ namespace BlackMisc
QStringList CXPlaneUtil::pluginSubdirectories(const QString &pluginDir)
{
const QString dirName = pluginDir.isEmpty() ? xplaneRootDir() : pluginDir;
if (!CDirectoryUtils::isDirExisting(dirName)) { return QStringList(); }
const QDir dir(dirName);
if (!dir.exists()) { return QStringList(); }
return dir.entryList(QDir::Dirs, QDir::Name | QDir::IgnoreCase);
}
@@ -180,7 +180,7 @@ namespace BlackMisc
if (!rootDir.isEmpty())
{
const QString xswiftbusDir = CFileUtils::appendFilePathsAndFixUnc(CXPlaneUtil::pluginDirFromRootDir(xplaneRootDir), CXPlaneUtil::xswiftbusPathName());
if (QDir(xswiftbusDir).exists())
if (CDirectoryUtils::isDirExisting(xswiftbusDir))
{
return xswiftbusDir;
}
@@ -197,7 +197,7 @@ namespace BlackMisc
if (!rootDir.isEmpty())
{
const QString xswiftbusLegacy = CFileUtils::appendFilePathsAndFixUnc(xplaneRootDir, legacyPath);
if (QDir(xswiftbusLegacy).exists())
if (CDirectoryUtils::isDirExisting(xswiftbusLegacy))
{
return xswiftbusLegacy;
}