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 // ever used with XPlane
const QString pluginDir = CXPlaneUtil::pluginDirFromRootDir(m_simulatorSettings.getSimulatorDirectoryOrDefault(CSimulatorInfo::XPLANE)); const QString pluginDir = CXPlaneUtil::pluginDirFromRootDir(m_simulatorSettings.getSimulatorDirectoryOrDefault(CSimulatorInfo::XPLANE));
const QDir dir(pluginDir); if (CDirectoryUtils::isDirExisting(pluginDir))
if (dir.exists())
{ {
// only check if we are on a XP machine // only check if we are on a XP machine
const QStringList conflicts = CXPlaneUtil::findConflictingPlugins(pluginDir); const QStringList conflicts = CXPlaneUtil::findConflictingPlugins(pluginDir);

View File

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

View File

@@ -9,9 +9,9 @@
//! \cond PRIVATE //! \cond PRIVATE
#include "blackmisc/directoryutils.h" #include "directoryutils.h"
#include "blackmisc/fileutils.h" #include "fileutils.h"
#include "blackmisc/range.h" #include "range.h"
#include "blackconfig/buildconfig.h" #include "blackconfig/buildconfig.h"
#include <QCoreApplication> #include <QCoreApplication>
#include <QDir> #include <QDir>
@@ -416,7 +416,7 @@ namespace BlackMisc
{ {
if (testDir.isEmpty()) { return false; } if (testDir.isEmpty()) { return false; }
const QDir dir(testDir); const QDir dir(testDir);
if (!dir.exists()) { return false; } if (!CDirectoryUtils::isDirExisting(dir)) { return false; }
return !dir.isEmpty(); return !dir.isEmpty();
} }
@@ -438,6 +438,33 @@ namespace BlackMisc
return dirs; 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> CDirectoryUtils::fileNamesToQSet(const QFileInfoList &fileInfoList)
{ {
QSet<QString> sl; QSet<QString> sl;

View File

@@ -18,6 +18,7 @@
#include <QSet> #include <QSet>
#include <QString> #include <QString>
#include <QDateTime> #include <QDateTime>
#include <QDir>
#include <QFileInfoList> #include <QFileInfoList>
namespace BlackMisc namespace BlackMisc
@@ -144,6 +145,14 @@ namespace BlackMisc
//! Get the existing directories //! Get the existing directories
static QStringList getExistingUnemptyDirectories(const QStringList &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 //! Result of directory comparison
struct DirComparison struct DirComparison
{ {

View File

@@ -7,9 +7,10 @@
* contained in the LICENSE file. * contained in the LICENSE file.
*/ */
#include "blackmisc/network/networkutils.h"
#include "blackmisc/math/mathutils.h"
#include "blackmisc/worker.h" #include "blackmisc/worker.h"
#include "blackmisc/fileutils.h" #include "blackmisc/fileutils.h"
#include "blackmisc/math/mathutils.h"
#include "blackconfig/buildconfig.h" #include "blackconfig/buildconfig.h"
#include <QCoreApplication> #include <QCoreApplication>
@@ -21,10 +22,12 @@
#include <QLockFile> #include <QLockFile>
#include <QTextStream> #include <QTextStream>
#include <QtGlobal> #include <QtGlobal>
#include <QMap>
#include <algorithm> #include <algorithm>
using namespace BlackConfig; using namespace BlackConfig;
using namespace BlackMisc::Math; using namespace BlackMisc::Math;
using namespace BlackMisc::Network;
namespace BlackMisc namespace BlackMisc
{ {
@@ -383,6 +386,59 @@ namespace BlackMisc
return fixedPaths; 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 CFileUtils::toWindowsLocalPath(const QString &path)
{ {
QString p = CFileUtils::fixWindowsUncPath(path); QString p = CFileUtils::fixWindowsUncPath(path);

View File

@@ -147,6 +147,15 @@ namespace BlackMisc
//! Fix UNC file paths //! Fix UNC file paths
static QStringList fixWindowsUncPaths(const QStringList &filePaths); 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 //! To Windows path using "\" delimiter
static QString toWindowsLocalPath(const QString &path); static QString toWindowsLocalPath(const QString &path);

View File

@@ -74,7 +74,14 @@ namespace BlackMisc
} }
process.start(); process.start();
process.waitForFinished(); 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) bool CNetworkUtils::canPing(const CUrl &url)
@@ -92,7 +99,7 @@ namespace BlackMisc
if (address.isNull()) { continue; } if (address.isNull()) { continue; }
if (address.protocol() == QAbstractSocket::IPv4Protocol) if (address.protocol() == QAbstractSocket::IPv4Protocol)
{ {
QString a = address.toString(); const QString a = address.toString();
ips.append(a); ips.append(a);
} }
} }

View File

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