Merge pull request #10441 from Atlante45/feat/launch-sandbox

Launch the Sandbox as early as possible
This commit is contained in:
Brad Hefta-Gaub 2017-05-16 20:52:23 -07:00 committed by GitHub
commit 254c6e9292
7 changed files with 204 additions and 244 deletions

View file

@ -563,11 +563,8 @@ const bool DEFAULT_DESKTOP_TABLET_BECOMES_TOOLBAR = true;
const bool DEFAULT_HMD_TABLET_BECOMES_TOOLBAR = false;
const bool DEFAULT_PREFER_AVATAR_FINGER_OVER_STYLUS = false;
Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bool runServer, QString runServerPathOption) :
Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
QApplication(argc, argv),
_shouldRunServer(runServer),
_runServerPath(runServerPathOption),
_runningMarker(this, RUNNING_MARKER_FILENAME),
_window(new MainWindow(desktop())),
_sessionRunTimer(startupTimer),
_previousSessionCrashed(setupEssentials(argc, argv)),
@ -622,8 +619,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
// make sure the debug draw singleton is initialized on the main thread.
DebugDraw::getInstance().removeMarker("");
_runningMarker.startRunningMarker();
PluginContainer* pluginContainer = dynamic_cast<PluginContainer*>(this); // set the container for any plugins that care
PluginManager::getInstance()->setContainer(pluginContainer);
@ -675,38 +670,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
static const QString OCULUS_STORE_ARG = "--oculus-store";
setProperty(hifi::properties::OCULUS_STORE, arguments().indexOf(OCULUS_STORE_ARG) != -1);
static const QString NO_UPDATER_ARG = "--no-updater";
static const bool noUpdater = arguments().indexOf(NO_UPDATER_ARG) != -1;
static const bool wantsSandboxRunning = shouldRunServer();
static bool determinedSandboxState = false;
static bool sandboxIsRunning = false;
SandboxUtils sandboxUtils;
// updateHeartbeat() because we are going to poll shortly...
updateHeartbeat();
sandboxUtils.ifLocalSandboxRunningElse([&]() {
qCDebug(interfaceapp) << "Home sandbox appears to be running.....";
determinedSandboxState = true;
sandboxIsRunning = true;
}, [&]() {
qCDebug(interfaceapp) << "Home sandbox does not appear to be running....";
if (wantsSandboxRunning) {
QString contentPath = getRunServerPath();
SandboxUtils::runLocalSandbox(contentPath, true, RUNNING_MARKER_FILENAME, noUpdater);
sandboxIsRunning = true;
}
determinedSandboxState = true;
});
// SandboxUtils::runLocalSandbox currently has 2 sec delay after spawning sandbox, so 4
// sec here is ok I guess. TODO: ping sandbox so we know it is up, perhaps?
quint64 MAX_WAIT_TIME = USECS_PER_SECOND * 4;
auto startWaiting = usecTimestampNow();
while (!determinedSandboxState && (usecTimestampNow() - startWaiting <= MAX_WAIT_TIME)) {
QCoreApplication::processEvents();
// updateHeartbeat() while polling so we don't scare the deadlock watchdog
updateHeartbeat();
usleep(USECS_PER_MSEC * 50); // 20hz
}
// start the nodeThread so its event loop is running
QThread* nodeThread = new QThread(this);
@ -1223,6 +1187,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
#endif
// If launched from Steam, let it handle updates
const QString HIFI_NO_UPDATER_COMMAND_LINE_KEY = "--no-updater";
bool noUpdater = arguments().indexOf(HIFI_NO_UPDATER_COMMAND_LINE_KEY) != -1;
if (!noUpdater) {
auto applicationUpdater = DependencyManager::get<AutoUpdater>();
connect(applicationUpdater.data(), &AutoUpdater::newVersionIsAvailable, dialogsManager.data(), &DialogsManager::showUpdateDialog);
@ -1465,110 +1431,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
const auto testScript = property(hifi::properties::TEST).toUrl();
scriptEngines->loadScript(testScript, false);
} else {
enum HandControllerType {
Vive,
Oculus
};
static const std::map<HandControllerType, int> MIN_CONTENT_VERSION = {
{ Vive, 1 },
{ Oculus, 27 }
};
// Get sandbox content set version
auto acDirPath = PathUtils::getAppDataPath() + "../../" + BuildInfo::MODIFIED_ORGANIZATION + "/assignment-client/";
auto contentVersionPath = acDirPath + "content-version.txt";
qCDebug(interfaceapp) << "Checking " << contentVersionPath << " for content version";
int contentVersion = 0;
QFile contentVersionFile(contentVersionPath);
if (contentVersionFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
QString line = contentVersionFile.readAll();
contentVersion = line.toInt(); // returns 0 if conversion fails
}
// Get controller availability
bool hasHandControllers = false;
HandControllerType handControllerType = Vive;
if (PluginUtils::isViveControllerAvailable()) {
hasHandControllers = true;
handControllerType = Vive;
} else if (PluginUtils::isOculusTouchControllerAvailable()) {
hasHandControllers = true;
handControllerType = Oculus;
}
// Check tutorial content versioning
bool hasTutorialContent = contentVersion >= MIN_CONTENT_VERSION.at(handControllerType);
// Check HMD use (may be technically available without being in use)
bool hasHMD = PluginUtils::isHMDAvailable();
bool isUsingHMD = hasHMD && hasHandControllers && _displayPlugin->isHmd();
Setting::Handle<bool> tutorialComplete { "tutorialComplete", false };
Setting::Handle<bool> firstRun { Settings::firstRun, true };
bool isTutorialComplete = tutorialComplete.get();
bool shouldGoToTutorial = isUsingHMD && hasTutorialContent && !isTutorialComplete;
qCDebug(interfaceapp) << "HMD:" << hasHMD << ", Hand Controllers: " << hasHandControllers << ", Using HMD: " << isUsingHMD;
qCDebug(interfaceapp) << "Tutorial version:" << contentVersion << ", sufficient:" << hasTutorialContent <<
", complete:" << isTutorialComplete << ", should go:" << shouldGoToTutorial;
// when --url in command line, teleport to location
const QString HIFI_URL_COMMAND_LINE_KEY = "--url";
int urlIndex = arguments().indexOf(HIFI_URL_COMMAND_LINE_KEY);
QString addressLookupString;
if (urlIndex != -1) {
addressLookupString = arguments().value(urlIndex + 1);
}
const QString TUTORIAL_PATH = "/tutorial_begin";
if (shouldGoToTutorial) {
if (sandboxIsRunning) {
qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
DependencyManager::get<AddressManager>()->goToLocalSandbox(TUTORIAL_PATH);
} else {
qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
if (firstRun.get()) {
showHelp();
}
if (addressLookupString.isEmpty()) {
DependencyManager::get<AddressManager>()->goToEntry();
} else {
DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
}
}
} else {
bool isFirstRun = firstRun.get();
if (isFirstRun) {
showHelp();
}
// If this is a first run we short-circuit the address passed in
if (isFirstRun) {
if (isUsingHMD) {
if (sandboxIsRunning) {
qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
DependencyManager::get<AddressManager>()->goToLocalSandbox();
} else {
qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
DependencyManager::get<AddressManager>()->goToEntry();
}
} else {
DependencyManager::get<AddressManager>()->goToEntry();
}
} else {
qCDebug(interfaceapp) << "Not first run... going to" << qPrintable(addressLookupString.isEmpty() ? QString("previous location") : addressLookupString);
DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
}
}
_connectionMonitor.init();
// After all of the constructor is completed, then set firstRun to false.
firstRun.set(false);
PROFILE_RANGE(render, "GetSandboxStatus");
auto reply = SandboxUtils::getStatus();
connect(reply, &QNetworkReply::finished, this, [=] {
handleSandboxStatus(reply);
});
}
// Monitor model assets (e.g., from Clara.io) added to the world that may need resizing.
@ -2474,6 +2341,118 @@ void Application::resizeGL() {
}
}
void Application::handleSandboxStatus(QNetworkReply* reply) {
PROFILE_RANGE(render, "HandleSandboxStatus");
bool sandboxIsRunning = SandboxUtils::readStatus(reply->readAll());
qDebug() << "HandleSandboxStatus" << sandboxIsRunning;
enum HandControllerType {
Vive,
Oculus
};
static const std::map<HandControllerType, int> MIN_CONTENT_VERSION = {
{ Vive, 1 },
{ Oculus, 27 }
};
// Get sandbox content set version
auto acDirPath = PathUtils::getAppDataPath() + "../../" + BuildInfo::MODIFIED_ORGANIZATION + "/assignment-client/";
auto contentVersionPath = acDirPath + "content-version.txt";
qCDebug(interfaceapp) << "Checking " << contentVersionPath << " for content version";
int contentVersion = 0;
QFile contentVersionFile(contentVersionPath);
if (contentVersionFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
QString line = contentVersionFile.readAll();
contentVersion = line.toInt(); // returns 0 if conversion fails
}
// Get controller availability
bool hasHandControllers = false;
HandControllerType handControllerType = Vive;
if (PluginUtils::isViveControllerAvailable()) {
hasHandControllers = true;
handControllerType = Vive;
} else if (PluginUtils::isOculusTouchControllerAvailable()) {
hasHandControllers = true;
handControllerType = Oculus;
}
// Check tutorial content versioning
bool hasTutorialContent = contentVersion >= MIN_CONTENT_VERSION.at(handControllerType);
// Check HMD use (may be technically available without being in use)
bool hasHMD = PluginUtils::isHMDAvailable();
bool isUsingHMD = hasHMD && hasHandControllers && _displayPlugin->isHmd();
Setting::Handle<bool> tutorialComplete{ "tutorialComplete", false };
Setting::Handle<bool> firstRun{ Settings::firstRun, true };
bool isTutorialComplete = tutorialComplete.get();
bool shouldGoToTutorial = isUsingHMD && hasTutorialContent && !isTutorialComplete;
qCDebug(interfaceapp) << "HMD:" << hasHMD << ", Hand Controllers: " << hasHandControllers << ", Using HMD: " << isUsingHMD;
qCDebug(interfaceapp) << "Tutorial version:" << contentVersion << ", sufficient:" << hasTutorialContent <<
", complete:" << isTutorialComplete << ", should go:" << shouldGoToTutorial;
// when --url in command line, teleport to location
const QString HIFI_URL_COMMAND_LINE_KEY = "--url";
int urlIndex = arguments().indexOf(HIFI_URL_COMMAND_LINE_KEY);
QString addressLookupString;
if (urlIndex != -1) {
addressLookupString = arguments().value(urlIndex + 1);
}
const QString TUTORIAL_PATH = "/tutorial_begin";
if (shouldGoToTutorial) {
if (sandboxIsRunning) {
qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
DependencyManager::get<AddressManager>()->goToLocalSandbox(TUTORIAL_PATH);
} else {
qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
if (firstRun.get()) {
showHelp();
}
if (addressLookupString.isEmpty()) {
DependencyManager::get<AddressManager>()->goToEntry();
} else {
DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
}
}
} else {
bool isFirstRun = firstRun.get();
if (isFirstRun) {
showHelp();
}
// If this is a first run we short-circuit the address passed in
if (isFirstRun) {
if (isUsingHMD) {
if (sandboxIsRunning) {
qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
DependencyManager::get<AddressManager>()->goToLocalSandbox();
} else {
qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
DependencyManager::get<AddressManager>()->goToEntry();
}
} else {
DependencyManager::get<AddressManager>()->goToEntry();
}
} else {
qCDebug(interfaceapp) << "Not first run... going to" << qPrintable(addressLookupString.isEmpty() ? QString("previous location") : addressLookupString);
DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
}
}
_connectionMonitor.init();
// After all of the constructor is completed, then set firstRun to false.
firstRun.set(false);
}
bool Application::importJSONFromURL(const QString& urlString) {
// we only load files that terminate in just .json (not .svo.json and not .ava.json)
// if they come from the High Fidelity Marketplace Assets CDN

View file

@ -112,17 +112,7 @@ class Application : public QApplication,
// TODO? Get rid of those
friend class OctreePacketProcessor;
private:
bool _shouldRunServer { false };
QString _runServerPath;
RunningMarker _runningMarker;
public:
// startup related getter/setters
bool shouldRunServer() const { return _shouldRunServer; }
bool hasRunServerPath() const { return !_runServerPath.isEmpty(); }
QString getRunServerPath() const { return _runServerPath; }
// virtual functions required for PluginContainer
virtual ui::Menu* getPrimaryMenu() override;
virtual void requestReset() override { resetSensors(true); }
@ -146,7 +136,7 @@ public:
static void initPlugins(const QStringList& arguments);
static void shutdownPlugins();
Application(int& argc, char** argv, QElapsedTimer& startup_time, bool runServer, QString runServerPathOption);
Application(int& argc, char** argv, QElapsedTimer& startup_time);
~Application();
void postLambdaEvent(std::function<void()> f) override;
@ -452,6 +442,8 @@ private slots:
void addAssetToWorldInfoTimeout();
void addAssetToWorldErrorTimeout();
void handleSandboxStatus(QNetworkReply* reply);
private:
static void initDisplay();
void init();

View file

@ -11,6 +11,7 @@
#include <thread>
#include <QCommandLineParser>
#include <QtCore/QProcess>
#include <QDebug>
#include <QDir>
#include <QLocalSocket>
@ -20,6 +21,7 @@
#include <BuildInfo.h>
#include <gl/OpenGLVersionChecker.h>
#include <SandboxUtils.h>
#include <SharedUtil.h>
@ -28,7 +30,6 @@
#include "InterfaceLogging.h"
#include "UserActivityLogger.h"
#include "MainWindow.h"
#include <QtCore/QProcess>
#ifdef HAS_BUGSPLAT
#include <BugSplat.h>
@ -50,50 +51,49 @@ int main(int argc, const char* argv[]) {
disableQtBearerPoll(); // Fixes wifi ping spikes
QElapsedTimer startupTime;
startupTime.start();
// Set application infos
QCoreApplication::setApplicationName(BuildInfo::INTERFACE_NAME);
QCoreApplication::setOrganizationName(BuildInfo::MODIFIED_ORGANIZATION);
QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN);
QCoreApplication::setApplicationVersion(BuildInfo::VERSION);
const QString& applicationName = getInterfaceSharedMemoryName();
bool instanceMightBeRunning = true;
QStringList arguments;
for (int i = 0; i < argc; ++i) {
arguments << argv[i];
}
#ifdef Q_OS_WIN
// Try to create a shared memory block - if it can't be created, there is an instance of
// interface already running. We only do this on Windows for now because of the potential
// for crashed instances to leave behind shared memory instances on unix.
QSharedMemory sharedMemory { applicationName };
instanceMightBeRunning = !sharedMemory.create(1, QSharedMemory::ReadOnly);
#endif
// allow multiple interfaces to run if this environment variable is set.
if (QProcessEnvironment::systemEnvironment().contains("HIFI_ALLOW_MULTIPLE_INSTANCES")) {
instanceMightBeRunning = false;
}
QCommandLineParser parser;
QCommandLineOption urlOption("url", "", "value");
QCommandLineOption noUpdaterOption("no-updater", "Do not show auto-updater");
QCommandLineOption checkMinSpecOption("checkMinSpec", "Check if machine meets minimum specifications");
QCommandLineOption runServerOption("runServer", "Whether to run the server");
QCommandLineOption serverContentPathOption("serverContentPath", "Where to find server content", "serverContentPath");
QCommandLineOption allowMultipleInstancesOption("allowMultipleInstances", "Allow multiple instances to run");
parser.addOption(urlOption);
parser.addOption(noUpdaterOption);
parser.addOption(checkMinSpecOption);
parser.addOption(runServerOption);
parser.addOption(serverContentPathOption);
parser.addOption(allowMultipleInstancesOption);
parser.parse(arguments);
bool runServer = parser.isSet(runServerOption);
bool serverContentPathOptionIsSet = parser.isSet(serverContentPathOption);
QString serverContentPathOptionValue = serverContentPathOptionIsSet ? parser.value(serverContentPathOption) : QString();
bool allowMultipleInstances = parser.isSet(allowMultipleInstancesOption);
const QString& applicationName = getInterfaceSharedMemoryName();
bool instanceMightBeRunning = true;
#ifdef Q_OS_WIN
// Try to create a shared memory block - if it can't be created, there is an instance of
// interface already running. We only do this on Windows for now because of the potential
// for crashed instances to leave behind shared memory instances on unix.
QSharedMemory sharedMemory{ applicationName };
instanceMightBeRunning = !sharedMemory.create(1, QSharedMemory::ReadOnly);
#endif
// allow multiple interfaces to run if this environment variable is set.
bool allowMultipleInstances = parser.isSet(allowMultipleInstancesOption) ||
QProcessEnvironment::systemEnvironment().contains("HIFI_ALLOW_MULTIPLE_INSTANCES");
if (allowMultipleInstances) {
instanceMightBeRunning = false;
}
@ -108,11 +108,6 @@ int main(int argc, const char* argv[]) {
// Try to connect - if we can't connect, interface has probably just gone down
if (socket.waitForConnected(LOCAL_SERVER_TIMEOUT_MS)) {
QCommandLineParser parser;
QCommandLineOption urlOption("url", "", "value");
parser.addOption(urlOption);
parser.process(arguments);
if (parser.isSet(urlOption)) {
QUrl url = QUrl(parser.value(urlOption));
if (url.isValid() && url.scheme() == HIFI_URL_SCHEME) {
@ -156,9 +151,6 @@ int main(int argc, const char* argv[]) {
}
}
QElapsedTimer startupTime;
startupTime.start();
// Debug option to demonstrate that the client's local time does not
// need to be in sync with any other network node. This forces clock
// skew for the individual client
@ -199,7 +191,21 @@ int main(int argc, const char* argv[]) {
int exitCode;
{
Application app(argc, const_cast<char**>(argv), startupTime, runServer, serverContentPathOptionValue);
RunningMarker runningMarker(nullptr, RUNNING_MARKER_FILENAME);
runningMarker.writeRunningMarkerFile();
bool noUpdater = parser.isSet(noUpdaterOption);
bool runServer = parser.isSet(runServerOption);
bool serverContentPathOptionIsSet = parser.isSet(serverContentPathOption);
QString serverContentPath = serverContentPathOptionIsSet ? parser.value(serverContentPathOption) : QString();
if (runServer) {
SandboxUtils::runLocalSandbox(serverContentPath, true, RUNNING_MARKER_FILENAME, noUpdater);
}
Application app(argc, const_cast<char**>(argv), startupTime);
// Now that the main event loop is setup, launch running marker thread
runningMarker.startRunningMarker();
// If we failed the OpenGLVersion check, log it.
if (override) {

View file

@ -9,63 +9,52 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QDataStream>
#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include "SandboxUtils.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkReply>
#include <QProcess>
#include <QStandardPaths>
#include <QThread>
#include <QTimer>
#include <NumericalConstants.h>
#include <SharedUtil.h>
#include <RunningMarker.h>
#include "SandboxUtils.h"
#include "NetworkAccessManager.h"
#include "NetworkLogging.h"
namespace SandboxUtils {
void SandboxUtils::ifLocalSandboxRunningElse(std::function<void()> localSandboxRunningDoThis,
std::function<void()> localSandboxNotRunningDoThat) {
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkReply* getStatus() {
auto& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest sandboxStatus(SANDBOX_STATUS_URL);
sandboxStatus.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
sandboxStatus.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
QNetworkReply* reply = networkAccessManager.get(sandboxStatus);
connect(reply, &QNetworkReply::finished, this, [reply, localSandboxRunningDoThis, localSandboxNotRunningDoThat]() {
if (reply->error() == QNetworkReply::NoError) {
auto statusData = reply->readAll();
auto statusJson = QJsonDocument::fromJson(statusData);
if (!statusJson.isEmpty()) {
auto statusObject = statusJson.object();
auto serversValue = statusObject.value("servers");
if (!serversValue.isUndefined() && serversValue.isObject()) {
auto serversObject = serversValue.toObject();
auto serversCount = serversObject.size();
const int MINIMUM_EXPECTED_SERVER_COUNT = 5;
if (serversCount >= MINIMUM_EXPECTED_SERVER_COUNT) {
localSandboxRunningDoThis();
return;
}
}
}
}
localSandboxNotRunningDoThat();
});
return networkAccessManager.get(sandboxStatus);
}
bool readStatus(QByteArray statusData) {
auto statusJson = QJsonDocument::fromJson(statusData);
void SandboxUtils::runLocalSandbox(QString contentPath, bool autoShutdown, QString runningMarkerName, bool noUpdater) {
QString applicationDirPath = QFileInfo(QCoreApplication::applicationFilePath()).path();
QString serverPath = applicationDirPath + "/server-console/server-console.exe";
qCDebug(networking) << "Application dir path is: " << applicationDirPath;
if (!statusJson.isEmpty()) {
auto statusObject = statusJson.object();
auto serversValue = statusObject.value("servers");
if (!serversValue.isUndefined() && serversValue.isObject()) {
auto serversObject = serversValue.toObject();
auto serversCount = serversObject.size();
const int MINIMUM_EXPECTED_SERVER_COUNT = 5;
if (serversCount >= MINIMUM_EXPECTED_SERVER_COUNT) {
return true;
}
}
}
return false;
}
void runLocalSandbox(QString contentPath, bool autoShutdown, QString runningMarkerName, bool noUpdater) {
QString serverPath = "./server-console/server-console.exe";
qCDebug(networking) << "Running marker path is: " << runningMarkerName;
qCDebug(networking) << "Server path is: " << serverPath;
qCDebug(networking) << "autoShutdown: " << autoShutdown;
qCDebug(networking) << "noUpdater: " << noUpdater;
@ -80,7 +69,7 @@ void SandboxUtils::runLocalSandbox(QString contentPath, bool autoShutdown, QStri
}
if (hasContentPath) {
QString serverContentPath = applicationDirPath + "/" + contentPath;
QString serverContentPath = "./" + contentPath;
args << "--contentPath" << serverContentPath;
}
@ -93,10 +82,8 @@ void SandboxUtils::runLocalSandbox(QString contentPath, bool autoShutdown, QStri
args << "--noUpdater";
}
qCDebug(networking) << applicationDirPath;
qCDebug(networking) << "Launching sandbox with:" << args;
qCDebug(networking) << QProcess::startDetached(serverPath, args);
// Sleep a short amount of time to give the server a chance to start
usleep(2000000); /// do we really need this??
}
}

View file

@ -12,21 +12,16 @@
#ifndef hifi_SandboxUtils_h
#define hifi_SandboxUtils_h
#include <functional>
#include <QtCore/QObject>
#include <QtCore/QString>
class QNetworkReply;
const QString SANDBOX_STATUS_URL = "http://localhost:60332/status";
namespace SandboxUtils {
const QString SANDBOX_STATUS_URL = "http://localhost:60332/status";
class SandboxUtils : public QObject {
Q_OBJECT
public:
/// determines if the local sandbox is likely running. It does not account for custom setups, and is only
/// intended to detect the standard local sandbox install.
void ifLocalSandboxRunningElse(std::function<void()> localSandboxRunningDoThis,
std::function<void()> localSandboxNotRunningDoThat);
static void runLocalSandbox(QString contentPath, bool autoShutdown, QString runningMarkerName, bool noUpdater);
QNetworkReply* getStatus();
bool readStatus(QByteArray statusData);
void runLocalSandbox(QString contentPath, bool autoShutdown, QString runningMarkerName, bool noUpdater);
};
#endif // hifi_SandboxUtils_h

View file

@ -33,11 +33,11 @@ void RunningMarker::startRunningMarker() {
_runningMarkerThread->setObjectName("Running Marker Thread");
_runningMarkerThread->start();
writeRunningMarkerFiler(); // write the first file, even before timer
writeRunningMarkerFile(); // write the first file, even before timer
_runningMarkerTimer = new QTimer();
QObject::connect(_runningMarkerTimer, &QTimer::timeout, [=](){
writeRunningMarkerFiler();
writeRunningMarkerFile();
});
_runningMarkerTimer->start(RUNNING_STATE_CHECK_IN_MSECS);
@ -53,7 +53,7 @@ RunningMarker::~RunningMarker() {
_runningMarkerThread->deleteLater();
}
void RunningMarker::writeRunningMarkerFiler() {
void RunningMarker::writeRunningMarkerFile() {
QFile runningMarkerFile(getFilePath());
// always write, even it it exists, so that it touches the files

View file

@ -27,10 +27,11 @@ public:
QString getFilePath();
static QString getMarkerFilePath(QString name);
protected:
void writeRunningMarkerFiler();
void writeRunningMarkerFile();
void deleteRunningMarkerFile();
private:
QObject* _parent { nullptr };
QString _name;
QThread* _runningMarkerThread { nullptr };