Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User directory config files #534

Merged
merged 10 commits into from
May 1, 2017
57 changes: 21 additions & 36 deletions apps/osvr_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,16 @@
#include <osvr/Util/Logger.h>
#include <osvr/Util/LogNames.h>
#include <osvr/Util/LogRegistry.h>
#include <osvr/Server/ConfigFilePaths.h>

// Library/third-party includes
#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/optional.hpp>

// Standard includes
#include <exception>
#include <fstream>
#include <vector>
#include <iostream>

namespace opt = boost::program_options;
namespace fs = boost::filesystem;

static osvr::server::ServerPtr server;
using ::osvr::util::log::OSVR_SERVER_LOG;
Expand All @@ -57,19 +53,15 @@ void handleShutdown() {
int main(int argc, char *argv[]) {
auto log = ::osvr::util::log::make_logger(OSVR_SERVER_LOG);

std::string configName; // server configuration filename
std::vector<std::string> configPaths;

opt::options_description optionsAll("All Options");
opt::options_description optionsVisible("Command Line Options");
opt::positional_options_description optionsPositional;

optionsPositional.add("config", -1);
optionsAll.add_options()(
"config",
opt::value<std::string>(&configName)
->default_value(osvr::server::getDefaultConfigFilename()),
"server configuration filename");
optionsVisible.add_options()
("config", "server configuration filename")
("help", "display this help message")
("verbose,v", "enable verbose logging")
("debug,d", "enable debug logging");
Expand Down Expand Up @@ -106,36 +98,29 @@ int main(int argc, char *argv[]) {
log->debug("Verbose logging enabled.");
}

configName = values["config"].as<std::string>();
if (values.count("config")) {
std::string configFileArgument = values["config"].as<std::string>();
log->info() << "Using config file " << configFileArgument << " from command line argument.";
configPaths = { configFileArgument };
} else {
log->info() << "Using default config files - pass a filename on the command "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the word "files" here a typo?

"line to use a different one.";
configPaths = osvr::server::getDefaultConfigFilePaths();
}

boost::optional<fs::path> configPath(configName);
try {
if (!fs::exists(*configPath)) {
log->warn() << "File '" << configName
<< "' not found. Using empty configuration.";
configPath = boost::none;
server = osvr::server::configureServerFromFirstFileInList(configPaths);
if (!server) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you've got trailing spaces - did you clang format your changes?

// only attempt to load the empty config if no arguments are passed.
if (!values.count("config")) {
log->info() << "Could not find a valid config file. Using default config object.";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this maybe better phrased "could not find config file with default name" or something like that? The user seeing this message wouldn't have passed a config file, so they might be confused as to why they're seeing this.

server = osvr::server::configureServerFromString("{ }");
} else {
if (fs::is_directory(*configPath)) {
log->error() << "'" << configName << "' is a directory.";
return -1;
} else if (!fs::is_regular_file(*configPath)) {
log->error() << "'" << configName << "' is special file.";
return -1;
}
return -1;
}
} catch (fs::filesystem_error &e) {
log->error() << "Could not open config file at '" << configName << "'.";
log->error() << "Reason " << e.what() << ".";
configPath = boost::none;
}

if (configPath) {
server = osvr::server::configureServerFromFile(configName);
} else {
server = osvr::server::configureServerFromString("{ }");
}

if (!server) {
log->error() << "Unknown error while creating server.";
return -1;
}

Expand Down
45 changes: 45 additions & 0 deletions inc/osvr/Server/ConfigFilePaths.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/** @file
@brief Platform specific search paths for osvr server config files.

@date 2017

@author
Sensics, Inc.
<http://sensics.com/osvr>
*/

// Copyright 2015 Sensics, Inc.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this 2015 code?

//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef INCLUDED_ConfigFilePaths_h_GUID_241E9C9C_0E0E_46B0_9DED_8F8059306192
#define INCLUDED_ConfigFilePaths_h_GUID_241E9C9C_0E0E_46B0_9DED_8F8059306192

// Internal Includes
#include <osvr/Server/Export.h>

// Library/third-party includes
// - none

// Standard includes
#include <vector>
#include <string>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't forget #include <string>.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

namespace osvr {
namespace server {

/// @brief this returns a vector of default server configuration file paths.
OSVR_SERVER_EXPORT std::vector<std::string> getDefaultConfigFilePaths();
}
}
#endif // INCLUDED_ConfigFilePaths_h_GUID_241E9C9C_0E0E_46B0_9DED_8F8059306192
130 changes: 14 additions & 116 deletions inc/osvr/Server/ConfigureServerFromFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,133 +35,31 @@
// - none

// Standard includes
#include <exception>
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
#include <string>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need #include <string>. And it looks like you can ditch iostream and fstream and exception (move 'em to the .cpp file). Same with the Log headers above.

namespace osvr {
namespace server {

inline const char *getDefaultConfigFilename() {
return "osvr_server_config.json";
}

/// @brief This is the basic common code of a server app's setup, ripped out
/// @brief This uses a file name to attempt to configure the server with
/// that config file.
/// Pass an empty string to use the default config.
/// This is the basic common code of a server app's setup, ripped out
/// of the main server app to make alternate server-acting apps simpler to
/// develop.
inline ServerPtr configureServerFromString(std::string const &json) {
auto log =
::osvr::util::log::make_logger(::osvr::util::log::OSVR_SERVER_LOG);

ServerPtr ret;
osvr::server::ConfigureServer srvConfig;
log->info() << "Constructing server as configured...";
try {
srvConfig.loadConfig(json);
ret = srvConfig.constructServer();
} catch (std::exception &e) {
log->error()
<< "Caught exception constructing server from JSON config "
"file: "
<< e.what();
return nullptr;
}

{
log->info() << "Loading auto-loadable plugins...";
srvConfig.loadAutoPlugins();
}

{
log->info() << "Loading plugins...";
srvConfig.loadPlugins();
if (!srvConfig.getSuccessfulPlugins().empty()) {
log->info() << "Successfully loaded the following plugins:";
for (auto const &plugin : srvConfig.getSuccessfulPlugins()) {
log->info() << " - " << plugin;
}
}
if (!srvConfig.getFailedPlugins().empty()) {
log->warn() << "Failed to load the following plugins:";
for (auto const &pluginError : srvConfig.getFailedPlugins()) {
log->warn() << " - " << pluginError.first << "\t"
<< pluginError.second;
}
}
}

{
log->info() << "Instantiating configured drivers...";
bool success = srvConfig.instantiateDrivers();
if (!srvConfig.getSuccessfulInstantiations().empty()) {
log->info() << "Successes:";
for (auto const &driver :
srvConfig.getSuccessfulInstantiations()) {
log->info() << " - " << driver;
}
}
if (!srvConfig.getFailedInstantiations().empty()) {
log->error() << "Errors:";
for (auto const &error : srvConfig.getFailedInstantiations()) {
log->error() << " - " << error.first << "\t"
<< error.second;
}
}
}

if (srvConfig.processExternalDevices()) {
log->info()
<< "External devices found and parsed from config file.";
}

if (srvConfig.processRoutes()) {
log->info() << "Routes found and parsed from config file.";
}

if (srvConfig.processAliases()) {
log->info() << "Aliases found and parsed from config file.";
}
OSVR_SERVER_EXPORT ServerPtr configureServerFromFile(std::string const &configName);

if (srvConfig.processDisplay()) {
log->info()
<< "Display descriptor found and parsed from config file.";
} else {
log->info()
<< "Using OSVR HDK for display configuration. "
"Did not find an alternate valid 'display' object in config "
"file.";
}
OSVR_SERVER_EXPORT ServerPtr configureServerFromString(std::string const &json);

if (srvConfig.processRenderManagerParameters()) {
log->info() << "RenderManager config found and parsed from the "
"config file.";
}

log->info() << "Triggering automatic hardware detection...";
ret->triggerHardwareDetect();

return ret;
}

/// @Brief Convenience wrapper for configureServerFromString().
inline ServerPtr configureServerFromFile(std::string const &configName) {
auto log =
::osvr::util::log::make_logger(::osvr::util::log::OSVR_SERVER_LOG);

ServerPtr ret;
log->info() << "Using config file '" << configName << "'.";
std::ifstream config(configName);
if (!config.good()) {
log->error() << "Could not open config file!";
log->error() << "Searched in the current directory; file may be "
"misspelled, missing, or in a different directory.";
return nullptr;
}

std::stringstream sstr;
sstr << config.rdbuf();
return configureServerFromString(sstr.str());
}
/// @brief This iterates over a vector that contains a list of potential
/// config files, and uses the first working one to create the server
/// instance.
OSVR_SERVER_EXPORT ServerPtr configureServerFromFirstFileInList(
std::vector<std::string> const &configNames);

} // namespace server
} // namespace osvr
Expand Down
3 changes: 3 additions & 0 deletions src/osvr/Server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ osvr_setup_lib_vars(Server)

set(API
"${HEADER_LOCATION}/ConfigureServer.h"
"${HEADER_LOCATION}/ConfigFilePaths.h"
"${HEADER_LOCATION}/ConfigureServerFromFile.h"
"${HEADER_LOCATION}/Server.h"
"${HEADER_LOCATION}/ServerPtr.h"
Expand All @@ -11,6 +12,8 @@ set(API

set(SOURCE
ConfigureServer.cpp
ConfigFilePaths.cpp
ConfigureServerFromFile.cpp
JSONResolvePossibleRef.h
JSONResolvePossibleRef.cpp
Server.cpp
Expand Down
Loading