From 08c8bd4aee3377b6bc4ce0000522013f6365a8a1 Mon Sep 17 00:00:00 2001
From: sale <sandi.fatic@memgraph.io>
Date: Tue, 20 Dec 2016 22:23:54 +0000
Subject: [PATCH] Initial configuration memgraph which needs review

Summary: MG configuration commit for review

Test Plan: manual

Reviewers: buda

Subscribers: buda

Differential Revision: https://memgraph.phacility.com/D24
---
 include/config/config.hpp       |   1 +
 include/utils/config/config.hpp | 104 ++++++++++++++++++--------------
 src/config/config.cpp           |   2 +-
 src/memgraph_bolt.cpp           |   3 +
 4 files changed, 64 insertions(+), 46 deletions(-)

diff --git a/include/config/config.hpp b/include/config/config.hpp
index fb15307f3..837340ae9 100644
--- a/include/config/config.hpp
+++ b/include/config/config.hpp
@@ -31,6 +31,7 @@ inline size_t to_int(std::string &&s) { return stoull(s); }
 
 // code uses this define for key access
 // _KEY_ is value from all possible keys that are listed above
+#define CONFIG_INIT() config::Config<config::MemgraphConfig>::instance().initialize()
 #define CONFIG(_KEY_) config::Config<config::MemgraphConfig>::instance()[_KEY_]
 
 #define CONFIG_INTEGER(_KEY_) config::to_int(CONFIG(_KEY_))
diff --git a/include/utils/config/config.hpp b/include/utils/config/config.hpp
index 7fcec7182..a23a2e795 100644
--- a/include/utils/config/config.hpp
+++ b/include/utils/config/config.hpp
@@ -1,63 +1,77 @@
 #pragma once
 
-#include <cstring>
-#include <string>
-#include <stdexcept>
 #include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <stdexcept>
+#include <string>
+
+#include <pwd.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 // TODO: isolate from caller (caller shouldn't know that his dependency is)
 // yaml-cpp
+#include "utils/command_line/arguments.hpp"
 #include "yaml-cpp/yaml.h"
 
-namespace config
-{
-
+namespace config {
+  
 template <class Definition>
-class Config
-{
-private:
-    YAML::Node _config;
+class Config {
+ private:
+  using KeyValueMap = std::map<std::string, std::string>;
 
-    Config()
-    {
-        // config places:             priority
-        //     1. default system         |     (/etc/name/config)
-        //     2. default user           |     (/home/user/.name/config)
-        //     3. ENV var                |     (PATH)
-        //     4. program argument      \ /    (PATH)
-       
-        if (const char* env_path = std::getenv(Definition::env_config_key))
-        {
-            _config = YAML::LoadFile(env_path);
-            // TODO: error handling
-        } 
-        else
-        {
-            _config = YAML::LoadFile(Definition::default_file_path);
-            // TODO: error handling
-        }
+  KeyValueMap dict;
 
-        // TODO:
-        //     * default system
-        //     * default user
-        //     * program argument
+  void load_configuration(std::string path) {
+    try {
+      YAML::Node node = YAML::LoadFile(path);
+    
+      for (YAML::const_iterator it = node.begin(); it != node.end(); ++it) {
+        dict[it->first.as<std::string>()] = it->second.as<std::string>();
+      }
+    } catch (std::exception ex) {
+      // configuration doesn't exist or invalid!!!
     }
+  }
 
-public:
-    static Config<Definition>& instance()
-    {
-        static Config<Definition> config;
-        return config;
-    }
+  Config() {
+    // config places:             priority
+    //     1. default system         |     (/etc/memgraph/config)
+    //     2. default user           |     (/home/user/.memgraph/config)
+    //     3. ENV var                |     (PATH)
+    //     4. program argument      \ /    (PATH)
 
-    void register_program_arguments()
-    {
-    }
+    // default system configuration
+    load_configuration(Definition::default_file_path);
 
-    std::string operator[](const char* key)
-    {
-        return _config[key].template as<std::string>();
+    // default user configuration
+    // fetches user configuration folder
+    std::string homedir;
+    if ((homedir = getenv("HOME")) == "") {
+      homedir = getpwuid(getuid())->pw_dir;
     }
+    homedir += "/.memgraph/config.yaml";
+    load_configuration(homedir);
+
+    // environment variable configuratoin
+    if (const char* env_path = std::getenv(Definition::env_config_key))
+      load_configuration(env_path);
+
+    // TODO add program arguments here
+    // Define how will we pass program args and which ones are we using and how.
+    // ProgramArguments::instance().get_arg();
+  }
+
+ public:
+  static Config<Definition>& instance() {
+    static Config<Definition> config;
+    return config;
+  }
+
+  std::string operator[](const char* key) {
+    return dict[key];
+  }
 };
-
 }
diff --git a/src/config/config.cpp b/src/config/config.cpp
index bf8f4700f..ef47d2445 100644
--- a/src/config/config.cpp
+++ b/src/config/config.cpp
@@ -4,6 +4,6 @@ namespace config
 {
 
 const char *MemgraphConfig::env_config_key = "MEMGRAPH_CONFIG";
-const char *MemgraphConfig::default_file_path = "config.yaml";
+const char *MemgraphConfig::default_file_path = "/etc/memgraph/config.yaml";
 
 }
diff --git a/src/memgraph_bolt.cpp b/src/memgraph_bolt.cpp
index 1c0585068..4de296343 100644
--- a/src/memgraph_bolt.cpp
+++ b/src/memgraph_bolt.cpp
@@ -9,6 +9,7 @@
 #include "logging/default.hpp"
 #include "logging/streams/stdout.hpp"
 
+#include "utils/config/config.hpp"
 #include "utils/signals/handler.hpp"
 #include "utils/stacktrace.hpp"
 #include "utils/terminate_handler.hpp"
@@ -57,6 +58,8 @@ int main(void) {
     exit(1);
   });
 
+  // CONFIG call
+
   io::Socket socket;
 
   try {