diff --git a/CMakeLists.txt b/CMakeLists.txt
index a30a07d..c5826ca 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -81,9 +81,9 @@ generate_compressed_bins(${CMAKE_BINARY_DIR} js/angular.min.js js/angular-route.
## Server
add_executable(laminard src/database.cpp src/main.cpp src/server.cpp src/laminar.cpp
- src/resources.cpp src/run.cpp src/node.cpp laminar.capnp.c++ ${COMPRESSED_BINS})
+ src/conf.cpp src/resources.cpp src/run.cpp src/node.cpp laminar.capnp.c++ ${COMPRESSED_BINS})
# TODO: some alternative to boost::filesystem?
-target_link_libraries(laminard capnp capnp-rpc kj-async kj boost_filesystem boost_system sqlite3 iniparser)
+target_link_libraries(laminard capnp capnp-rpc kj-async kj boost_filesystem boost_system sqlite3)
## Client
add_executable(laminarc src/client.cpp laminar.capnp.c++)
diff --git a/src/conf.cpp b/src/conf.cpp
new file mode 100644
index 0000000..4fa58ad
--- /dev/null
+++ b/src/conf.cpp
@@ -0,0 +1,39 @@
+///
+/// Copyright 2015 Oliver Giles
+///
+/// This file is part of Laminar
+///
+/// Laminar is free software: you can redistribute it and/or modify
+/// it under the terms of the GNU General Public License as published by
+/// the Free Software Foundation, either version 3 of the License, or
+/// (at your option) any later version.
+///
+/// Laminar is distributed in the hope that it will be useful,
+/// but WITHOUT ANY WARRANTY; without even the implied warranty of
+/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+/// GNU General Public License for more details.
+///
+/// You should have received a copy of the GNU General Public License
+/// along with Laminar. If not, see
+///
+#include "conf.h"
+
+#include
+
+template <>
+int StringMap::convert(std::string e) { return atoi(e.c_str()); }
+
+StringMap parseConfFile(const char* path) {
+ StringMap result;
+ std::fstream f(path);
+ std::string line;
+ while(std::getline(f, line)) {
+ if(line[0] == '#')
+ continue;
+ int p = line.find('=');
+ if(p > 0) {
+ result.emplace(line.substr(0, p), line.substr(p+1));
+ }
+ }
+ return result;
+}
diff --git a/src/conf.h b/src/conf.h
new file mode 100644
index 0000000..152a908
--- /dev/null
+++ b/src/conf.h
@@ -0,0 +1,44 @@
+///
+/// Copyright 2015 Oliver Giles
+///
+/// This file is part of Laminar
+///
+/// Laminar is free software: you can redistribute it and/or modify
+/// it under the terms of the GNU General Public License as published by
+/// the Free Software Foundation, either version 3 of the License, or
+/// (at your option) any later version.
+///
+/// Laminar is distributed in the hope that it will be useful,
+/// but WITHOUT ANY WARRANTY; without even the implied warranty of
+/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+/// GNU General Public License for more details.
+///
+/// You should have received a copy of the GNU General Public License
+/// along with Laminar. If not, see
+///
+#ifndef _LAMINAR_CONF_H_
+#define _LAMINAR_CONF_H_
+
+#include
+
+class StringMap : public std::unordered_map {
+public:
+ template
+ T get(std::string key, T fallback = T()) {
+ auto it = find(key);
+ return it != end() ? convert(it->second) : fallback;
+ }
+private:
+ template
+ T convert(std::string e) { return e; }
+};
+template <>
+int StringMap::convert(std::string e);
+
+// Reads a file by line into a list of key/value pairs
+// separated by the first '=' character. Discards lines
+// beginning with '#'
+StringMap parseConfFile(const char* path);
+
+
+#endif // _LAMINAR_CONF_H_
diff --git a/src/laminar.cpp b/src/laminar.cpp
index 9cf1fc9..0860afe 100644
--- a/src/laminar.cpp
+++ b/src/laminar.cpp
@@ -18,9 +18,9 @@
///
#include "laminar.h"
#include "server.h"
+#include "conf.h"
#include
-#include
#include
#include
@@ -61,11 +61,8 @@ constexpr const char* BASE_CFG_DIR = "/home/og/dev/laminar/cfg";
typedef std::string str;
-Laminar::Laminar(const char* configFile) {
- // read params from config file
- conf = iniparser_load(configFile);
- KJ_REQUIRE(conf != nullptr, "Could not parse", configFile);
- homeDir = iniparser_getstring(conf, ":LAMINAR_HOME", "/var/lib/laminar");
+Laminar::Laminar() {
+ homeDir = getenv("LAMINAR_HOME") ?: "/var/lib/laminar";
db = new Database((fs::path(homeDir)/"laminar.sqlite").string().c_str());
// Prepare database for first use
@@ -253,14 +250,13 @@ void Laminar::sendStatus(LaminarClient* client) {
}
Laminar::~Laminar() {
- iniparser_freedict(conf);
delete db;
delete srv;
}
void Laminar::run() {
- const char* listen_rpc = iniparser_getstring(conf, ":LAMINAR_BIND_RPC", INTADDR_RPC_DEFAULT);
- const char* listen_http = iniparser_getstring(conf, ":LAMINAR_BIND_HTTP", INTADDR_HTTP_DEFAULT);
+ const char* listen_rpc = getenv("LAMINAR_BIND_RPC") ?: INTADDR_RPC_DEFAULT;
+ const char* listen_http = getenv("LAMINAR_BIND_HTTP") ?: INTADDR_HTTP_DEFAULT;
srv = new Server(*this, listen_rpc, listen_http);
@@ -275,30 +271,25 @@ void Laminar::stop() {
bool Laminar::loadConfiguration() {
NodeMap nm;
- fs::directory_iterator dit(fs::path(homeDir)/"cfg"/"nodes");
- for(fs::directory_entry& it : dit) {
- if(!fs::is_directory(it.status()))
- continue;
+ fs::path nodeCfg = fs::path(homeDir)/"cfg"/"nodes";
- fs::directory_entry config(it.path()/"config");
- if(!fs::is_regular_file(config.status()))
- continue;
+ if(fs::is_directory(nodeCfg)) {
+ fs::directory_iterator dit(nodeCfg);
+ for(fs::directory_entry& it : dit) {
+ if(!fs::is_directory(it.status()))
+ continue;
- dictionary* ini = iniparser_load(config.path().string().c_str());
- if(!ini) {
- KJ_LOG(ERROR, "Could not parse node config", config.path().string());
- continue;
+ fs::directory_entry config(it.path()/"config");
+ if(!fs::is_regular_file(config.status()))
+ continue;
+
+ StringMap conf = parseConfFile(config.path().string().c_str());
+
+ Node node;
+ node.name = it.path().filename().string();
+ node.numExecutors = conf.get("EXECUTORS", 6);
+ nm.emplace(node.name, std::move(node));
}
-
- int executors = iniparser_getint(ini, ":EXECUTORS", 6);
-
- Node node;
- node.name = it.path().filename().string();
- node.numExecutors = executors;
- nm.emplace(node.name, std::move(node));
-
- iniparser_freedict(ini);
-
}
if(nm.empty()) {
diff --git a/src/laminar.h b/src/laminar.h
index a0e175b..28dc9fa 100644
--- a/src/laminar.h
+++ b/src/laminar.h
@@ -30,7 +30,6 @@
typedef std::unordered_map NodeMap;
struct Server;
-struct _dictionary_; // from iniparser
// The main class implementing the application's business logic.
// It owns a Server to manage the HTTP/websocket and Cap'n Proto RPC
@@ -38,7 +37,7 @@ struct _dictionary_; // from iniparser
// the LaminarClient objects (see interface.h)
class Laminar : public LaminarInterface {
public:
- Laminar(const char* configFile);
+ Laminar();
~Laminar();
// Runs the application forever
@@ -81,7 +80,6 @@ private:
RunSet activeJobs;
Database* db;
Server* srv;
- _dictionary_* conf;
NodeMap nodes;
std::string homeDir;
std::set clients;
diff --git a/src/main.cpp b/src/main.cpp
index 0d0e427..b42385f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -31,12 +31,8 @@ int main(int argc, char** argv) {
}
}
- const char* configFile = getenv("LAMINAR_CONF_FILE");
- if(!configFile || !*configFile)
- configFile = "/etc/laminar.conf";
-
do {
- Laminar laminar(configFile);
+ Laminar laminar;
sigHandler = [&](){
KJ_LOG(INFO, "Received SIGINT");
laminar.stop();