clean up config-cache so it can encapsulate different storage mechanisms
authorJim Morris <morris@wolfman.com>
Fri, 11 Apr 2014 22:39:10 +0000 (15:39 -0700)
committerJim Morris <morris@wolfman.com>
Fri, 11 Apr 2014 22:39:10 +0000 (15:39 -0700)
fix various config realted bugs along the way

src/libs/Config.cpp
src/libs/Config.h
src/libs/ConfigCache.cpp
src/libs/ConfigCache.h
src/libs/ConfigValue.cpp
src/libs/ConfigValue.h
src/main.cpp
src/modules/tools/temperaturecontrol/TemperatureControl.cpp
src/modules/utils/configurator/Configurator.cpp

index afbf0c9..73fd954 100644 (file)
@@ -19,12 +19,13 @@ using namespace std;
 #include "libs/SerialMessage.h"
 #include "libs/ConfigSources/FileConfigSource.h"
 #include "libs/ConfigSources/FirmConfigSource.h"
+#include "StreamOutputPool.h"
 
 // Add various config sources. Config can be fetched from several places.
 // All values are read into a cache, that is then used by modules to read their configuration
 Config::Config()
 {
-    this->config_cache_loaded = false;
+    this->config_cache = NULL;
 
     // Config source for firm config found in src/config.default
     this->config_sources.push_back( new FirmConfigSource("firm") );
@@ -54,12 +55,14 @@ void Config::on_console_line_received( void *argument ) {}
 // Set a value in the config cache, but not in any config source
 void Config::set_string( string setting, string value )
 {
+    if(!is_config_cache_loaded()) return;
+
     ConfigValue *cv = new ConfigValue;
     cv->found = true;
     get_checksums(cv->check_sums, setting);
     cv->value = value;
 
-    this->config_cache.replace_or_push_back(cv);
+    this->config_cache->replace_or_push_back(cv);
 
     THEKERNEL->call_event(ON_CONFIG_RELOAD);
 }
@@ -67,46 +70,29 @@ void Config::set_string( string setting, string value )
 // Get a list of modules, used by module "pools" that look for the "enable" keyboard to find things like "moduletype.modulename.enable" as the marker of a new instance of a module
 void Config::get_module_list(vector<uint16_t> *list, uint16_t family)
 {
-    for( unsigned int i = 1; i < this->config_cache.size(); i++) {
-        ConfigValue *value = this->config_cache.at(i);
-        //if( value->check_sums.size() == 3 && value->check_sums.at(2) == CHECKSUM("enable") && value->check_sums.at(0) == family ){
-        if( value->check_sums[2] == CHECKSUM("enable") && value->check_sums[0] == family ) {
-            // We found a module enable for this family, add it's number
-            list->push_back(value->check_sums[1]);
-        }
-    }
+    this->config_cache->collect(family, CHECKSUM("enable"), list);
 }
 
-
 // Command to load config cache into buffer for multiple reads during init
-void Config::config_cache_load()
+void Config::config_cache_load(bool parse)
 {
-
     // First clear the cache
     this->config_cache_clear();
 
-    // First element is a special empty ConfigValue for values not found
-    ConfigValue *result = new ConfigValue;
-    this->config_cache.push_back(result);
-
-    // For each ConfigSource in our stack
-    for( ConfigSource *source : this->config_sources ) {
-        source->transfer_values_to_cache(&this->config_cache);
+    this->config_cache= new ConfigCache;
+    if(parse) {
+        // For each ConfigSource in our stack
+        for( ConfigSource *source : this->config_sources ) {
+            source->transfer_values_to_cache(this->config_cache);
+        }
     }
-
-    this->config_cache_loaded = true;
 }
 
 // Command to clear the config cache after init
 void Config::config_cache_clear()
 {
-    for (ConfigValue *i : this->config_cache)  {
-        delete i;
-    }
-
-    //this->config_cache.clear(); // does not release vector memory
-    ConfigCache().swap(this->config_cache);   //  makes sure the vector releases its memory
-    this->config_cache_loaded = false;
+    delete this->config_cache;
+    this->config_cache= NULL;
 }
 
 // Three ways to read a value from the config, depending on adress length
@@ -119,56 +105,25 @@ ConfigValue *Config::value(uint16_t check_sum_a, uint16_t check_sum_b, uint16_t
     return this->value(check_sums);
 }
 
-ConfigValue *Config::value(uint16_t check_sum_a, uint16_t check_sum_b)
-{
-    uint16_t check_sums[3];
-    check_sums[0] = check_sum_a;
-    check_sums[1] = check_sum_b;
-    check_sums[2] = 0x0000;
-    return this->value(check_sums);
-}
-
-ConfigValue *Config::value(uint16_t check_sum)
-{
-    uint16_t check_sums[3];
-    check_sums[0] = check_sum;
-    check_sums[1] = 0x0000;
-    check_sums[2] = 0x0000;
-    return this->value(check_sums);
-}
-
 // Get a value from the configuration as a string
 // Because we don't like to waste space in Flash with lengthy config parameter names, we take a checksum instead so that the name does not have to be stored
 // See get_checksum
 ConfigValue *Config::value(uint16_t check_sums[])
 {
-    bool cache_preloaded = this->config_cache_loaded;
-    if( !cache_preloaded ) {
-        this->config_cache_load();
-    }
-    ConfigValue *result = this->config_cache[0];
-
-    for( unsigned int i = 1; i < this->config_cache.size(); i++) {
-        // If this line matches the checksum
-        bool match = true;
-        unsigned int counter = 0;
-        while(check_sums[counter] != 0x0000 && counter <= 2 ) {
-            if(this->config_cache[i]->check_sums[counter] != check_sums[counter] ) {
-                match = false;
-                break;
-            }
-            counter++;
-        }
-        if( match == false ) {
-            continue;
-        }
-        result = this->config_cache[i];
-        break;
+    if( !is_config_cache_loaded() ) {
+        THEKERNEL->streams->printf("ERROR: calling value after config cache has been cleared\n");
+        // note this will cause whatever called it to blow up!
+        return NULL;
     }
 
-    if( !cache_preloaded ) {
-        this->config_cache_clear();
+    ConfigValue *result = this->config_cache->lookup(check_sums);
+
+    if(result == NULL) {
+        // create a dummy value for this to play with, each call requires it's own value not a shared one
+        result= new ConfigValue(check_sums);
+        config_cache->add(result);
     }
+
     return result;
 }
 
index 3e9cca0..ac19973 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef CONFIG_H
 #define CONFIG_H
 
-#include "ConfigCache.h"
 
 using namespace std;
 #include <vector>
@@ -16,6 +15,7 @@ using namespace std;
 
 class ConfigValue;
 class ConfigSource;
+class ConfigCache;
 
 class Config : public Module {
     public:
@@ -23,22 +23,23 @@ class Config : public Module {
 
         void on_module_loaded();
         void on_console_line_received( void* argument );
-        void config_cache_load();
+        void config_cache_load(bool parse= true);
         void config_cache_clear();
         void set_string( string setting , string value);
 
-        ConfigValue* value(uint16_t check_sum);
-        ConfigValue* value(uint16_t check_sum_a, uint16_t check_sum_b);
-        ConfigValue* value(uint16_t check_sum_a, uint16_t check_sum_b, uint16_t check_sum_c );
+        ConfigValue* value(uint16_t check_sum_a, uint16_t check_sum_b= 0, uint16_t check_sum_c= 0 );
         ConfigValue* value(uint16_t check_sums[3] );
 
         void get_module_list(vector<uint16_t>* list, uint16_t family);
+        bool is_config_cache_loaded() { return config_cache != NULL; };    // Whether or not the cache is currently popluated
 
+        friend class  Configurator;
+
+    private:
         bool   has_characters(uint16_t check_sum, string str );
 
-        ConfigCache config_cache;             // A cache in which ConfigValues are kept
+        ConfigCache* config_cache;            // A cache in which ConfigValues are kept
         vector<ConfigSource*> config_sources; // A list of all possible coniguration sources
-        bool   config_cache_loaded;           // Whether or not the cache is currently popluated
 };
 
 #endif
index 2675504..764c0d8 100644 (file)
@@ -1,37 +1,85 @@
 #include "ConfigCache.h"
 #include "ConfigValue.h"
 
+#include "libs/StreamOutput.h"
+
+ConfigCache::ConfigCache()
+{
+}
+
+ConfigCache::~ConfigCache()
+{
+    clear();
+}
+
+void ConfigCache::clear()
+{
+    for (ConfigValue *i : store)  {
+        delete i;
+    }
+    vector<ConfigValue*>().swap(store);   //  makes sure the vector releases its memory
+}
+
 // If we find an existing value, replace it, otherwise, push it at the back of the list
 void ConfigCache::replace_or_push_back(ConfigValue *new_value)
 {
 
     bool value_exists = false;
+
     // For each already existing element
-    for( unsigned int i = 1; i < this->size(); i++) {
+    for(ConfigValue*& i: store) {
         // If this configvalue matches the checksum
         bool match = true;
         unsigned int counter = 0;
         while( counter < 3 && new_value->check_sums[counter] != 0x0000 ) {
-            if(this->at(i)->check_sums[counter] != new_value->check_sums[counter]  ) {
+            if(i->check_sums[counter] != new_value->check_sums[counter]  ) {
                 match = false;
                 break;
             }
             counter++;
         }
-        if( match == false ) {
+        if( !match ) {
             continue;
         }
         value_exists = true;
 
         // Replace with the provided value
-        delete this->at(i);
-        this->at(i) = new_value;
+        i=  new_value;
         break;
     }
 
     // Value does not already exists, add to the list
-    if( value_exists == false ) {
-        this->push_back(new_value);
+    if( !value_exists ) {
+        store.push_back(new_value);
+    }
+
+}
+
+ConfigValue *ConfigCache::lookup(const uint16_t *check_sums) const
+{
+   for( ConfigValue *cv : store) {
+        if(memcmp(check_sums, cv->check_sums, sizeof(cv->check_sums)) == 0)
+            return cv;
     }
 
+    return NULL;
+}
+
+void ConfigCache::collect(uint16_t family, uint16_t cs, vector<uint16_t> *list)
+{
+    for( ConfigValue *value : store ) {
+        if( value->check_sums[2] == cs && value->check_sums[0] == family ) {
+            // We found a module enable for this family, add it's number
+            list->push_back(value->check_sums[1]);
+        }
+    }
+}
+
+void ConfigCache::dump(StreamOutput *stream)
+{
+    int l= 1;
+    for( ConfigValue *v : store ) {
+        stream->printf("%3d - %04X %04X %04X : '%s' - found: %d, default: %d, default-double: %f, default-int: %d\n",
+            l++, v->check_sums[0], v->check_sums[1], v->check_sums[2], v->value.c_str(), v->found, v->default_set, v->default_double, v->default_int );
+    }
 }
index 2793707..535175b 100644 (file)
 
 using namespace std;
 #include <vector>
+#include <stdint.h>
 
 class ConfigValue;
+class StreamOutput;
 
-class ConfigCache : public std::vector<ConfigValue*> {
+class ConfigCache {
     public:
-        ConfigCache(){}
+        ConfigCache();
+        ~ConfigCache();
+        void clear();
+
+        void add(ConfigValue* v) { store.push_back(v); }
+
+        // lookup and return the entru that matches the check sums,return NULL if not found
+        ConfigValue *lookup(const uint16_t *check_sums) const;
+
+        // collect enabled checksums of the given family
+        void collect(uint16_t family, uint16_t cs, vector<uint16_t> *list);
 
         // If we find an existing value, replace it, otherwise, push it at the back of the list
         void replace_or_push_back(ConfigValue* new_value);
 
+        // used for debugging, dumps the cache to a stream
+        void dump(StreamOutput *stream);
+
+    private:
+        vector<ConfigValue*> store;
 };
 
 
index 7958402..486b04b 100644 (file)
@@ -7,7 +7,7 @@
 #include "Pwm.h"
 
 
-#define printErrorandExit(...) THEKERNEL->streams->printf(__VA_ARGS__); exit(1);
+#define printErrorandExit(...) THEKERNEL->streams->printf(__VA_ARGS__); // exit(1);
 
 #include <vector>
 #include <stdio.h>
@@ -19,15 +19,43 @@ ConfigValue::ConfigValue()
     this->check_sums[0] = 0x0000;
     this->check_sums[1] = 0x0000;
     this->check_sums[2] = 0x0000;
+    this->default_double= 0.0F;
+    this->default_int= 0;
+    this->value= "";
+}
+
+ConfigValue::ConfigValue(uint16_t *cs) {
+    memcpy(this->check_sums, cs, sizeof(this->check_sums));
+    this->found = false;
+    this->default_set = false;
+    this->value= "";
+}
+
+ConfigValue::ConfigValue(const ConfigValue& to_copy)
+{
+    this->found = to_copy.found;
+    this->default_set = to_copy.default_set;
+    memcpy(this->check_sums, to_copy.check_sums, sizeof(this->check_sums));
+    this->value.assign(to_copy.value);
+}
+
+ConfigValue& ConfigValue::operator= (const ConfigValue& to_copy)
+{
+    if( this != &to_copy ){
+        this->found = to_copy.found;
+        this->default_set = to_copy.default_set;
+        memcpy(this->check_sums, to_copy.check_sums, sizeof(this->check_sums));
+        this->value.assign(to_copy.value);
+    }
+    return *this;
 }
 
 ConfigValue *ConfigValue::required()
 {
-    if( this->found == true ) {
-        return this;
-    } else {
+    if( !this->found ) {
         printErrorandExit("could not find config setting, please see http://smoothieware.org/configuring-smoothie\r\n");
     }
+    return this;
 }
 
 float ConfigValue::as_number()
@@ -37,9 +65,10 @@ float ConfigValue::as_number()
     } else {
         char *endptr = NULL;
         string str = remove_non_number(this->value);
-        float result = strtof(str.c_str(), &endptr);
-        if( endptr <= str.c_str() ) {
-            printErrorandExit("config setting with value '%s' and checksums[%u,%u,%u] is not a valid number, please see http://smoothieware.org/configuring-smoothie\r\n", this->value.c_str(), this->check_sums[0], this->check_sums[1], this->check_sums[2] );
+        const char *cp= str.c_str();
+        float result = strtof(cp, &endptr);
+        if( endptr <= cp ) {
+            printErrorandExit("config setting with value '%s' and checksums[%04X,%04X,%04X] is not a valid number, please see http://smoothieware.org/configuring-smoothie\r\n", this->value.c_str(), this->check_sums[0], this->check_sums[1], this->check_sums[2] );
         }
         return result;
     }
@@ -52,9 +81,10 @@ int ConfigValue::as_int()
     } else {
         char *endptr = NULL;
         string str = remove_non_number(this->value);
-        int result = strtol(str.c_str(), &endptr, 10);
-        if( endptr <= str.c_str() ) {
-            printErrorandExit("config setting with value '%s' and checksums[%u,%u,%u] is not a valid number, please see http://smoothieware.org/configuring-smoothie\r\n", this->value.c_str(), this->check_sums[0], this->check_sums[1], this->check_sums[2] );
+        const char *cp= str.c_str();
+        int result = strtol(cp, &endptr, 10);
+        if( endptr <= cp ) {
+            printErrorandExit("config setting with value '%s' and checksums[%04X,%04X,%04X] is not a valid int, please see http://smoothieware.org/configuring-smoothie\r\n", this->value.c_str(), this->check_sums[0], this->check_sums[1], this->check_sums[2] );
         }
         return result;
     }
@@ -68,13 +98,9 @@ std::string ConfigValue::as_string()
 bool ConfigValue::as_bool()
 {
     if( this->found == false && this->default_set == true ) {
-        return this->default_double;
+        return this->default_int;
     } else {
-        if( this->value.find_first_of("ty1") != string::npos ) {
-            return true;
-        } else {
-            return false;
-        }
+        return this->value.find_first_of("ty1") != string::npos;
     }
 }
 
@@ -82,7 +108,7 @@ ConfigValue *ConfigValue::by_default(int val)
 {
     this->default_set = true;
     this->default_int = val;
-    this->default_double = val;
+    this->default_double = val; // we need to set both becuase sometimes an integer is passed when it should be a float
     return this;
 }
 
@@ -103,7 +129,7 @@ ConfigValue *ConfigValue::by_default(string val)
     return this;
 }
 
-bool ConfigValue::has_characters( string mask )
+bool ConfigValue::has_characters( const char *mask )
 {
     if( this->value.find_first_of(mask) != string::npos ) {
         return true;
@@ -114,6 +140,6 @@ bool ConfigValue::has_characters( string mask )
 
 bool ConfigValue::is_inverted()
 {
-    return this->has_characters(string("!"));
+    return this->has_characters("!");
 }
 
index 459ab4e..092fc10 100644 (file)
@@ -8,29 +8,39 @@
 #ifndef CONFIGVALUE_H
 #define CONFIGVALUE_H
 
-using namespace std;
 #include <string>
+using std::string;
 
 class ConfigValue{
     public:
         ConfigValue();
+        ConfigValue(uint16_t *check_sums);
+        ConfigValue(const ConfigValue& to_copy);
+        ConfigValue& operator= (const ConfigValue& to_copy);
 
         ConfigValue* required();
         float as_number();
         int as_int();
-        string as_string();
         bool as_bool();
+        string as_string();
 
         ConfigValue* by_default(float val);
         ConfigValue* by_default(string val);
         ConfigValue* by_default(int val);
-        bool has_characters( string mask );
         bool is_inverted();
 
+
+        friend class ConfigCache;
+        friend class Config;
+        friend class ConfigSource;
+        friend class Configurator;
+
+    private:
+        bool has_characters( const char* mask );
+        string value;
         int default_int;
         float default_double;
         uint16_t check_sums[3];
-        string value;
         bool found;
         bool default_set;
 };
index dad0577..bf4780f 100644 (file)
@@ -45,6 +45,8 @@
 #include "version.h"
 #include "system_LPC17xx.h"
 
+#include "mbed.h"
+
 #define second_usb_serial_enable_checksum  CHECKSUM("second_usb_serial_enable")
 #define disable_msd_checksum  CHECKSUM("msd_disable")
 #define disable_leds_checksum  CHECKSUM("leds_disable")
@@ -79,6 +81,11 @@ int main() {
         leds[i]= 0;
     }
 
+    Timer timer;
+    timer.start();
+    float begin, end;
+    begin = timer.read();
+
     Kernel* kernel = new Kernel();
 
     kernel->streams->printf("Smoothie Running @%ldMHz\r\n", SystemCoreClock / 1000000);
@@ -174,6 +181,9 @@ int main() {
         }
     }
 
+    end = timer.read();
+    kernel->streams->printf("boot time= %f\n", end-begin);
+
     uint16_t cnt= 0;
     // Main loop
     while(1){
index 241cea9..1a8214b 100644 (file)
@@ -114,12 +114,12 @@ void TemperatureControl::on_config_reload(void* argument){
 
     // Preset values for various common types of thermistors
     ConfigValue* thermistor = THEKERNEL->config->value(temperature_control_checksum, this->name_checksum, thermistor_checksum);
-    if(       thermistor->value.compare("EPCOS100K"    ) == 0 ){ // Default
-    }else if( thermistor->value.compare("RRRF100K"     ) == 0 ){ this->beta = 3960;
-    }else if( thermistor->value.compare("RRRF10K"      ) == 0 ){ this->beta = 3964; this->r0 = 10000; this->r1 = 680; this->r2 = 1600;
-    }else if( thermistor->value.compare("Honeywell100K") == 0 ){ this->beta = 3974;
-    }else if( thermistor->value.compare("Semitec"      ) == 0 ){ this->beta = 4267;
-    }else if( thermistor->value.compare("HT100K"       ) == 0 ){ this->beta = 3990; }
+    if(       thermistor->as_string().compare("EPCOS100K"    ) == 0 ){ // Default
+    }else if( thermistor->as_string().compare("RRRF100K"     ) == 0 ){ this->beta = 3960;
+    }else if( thermistor->as_string().compare("RRRF10K"      ) == 0 ){ this->beta = 3964; this->r0 = 10000; this->r1 = 680; this->r2 = 1600;
+    }else if( thermistor->as_string().compare("Honeywell100K") == 0 ){ this->beta = 3974;
+    }else if( thermistor->as_string().compare("Semitec"      ) == 0 ){ this->beta = 4267;
+    }else if( thermistor->as_string().compare("HT100K"       ) == 0 ){ this->beta = 3990; }
 
     // Preset values are overriden by specified values
     this->r0 =                  THEKERNEL->config->value(temperature_control_checksum, this->name_checksum, r0_checksum  )->by_default(this->r0  )->as_number();               // Stated resistance eg. 100K
index 0d95b79..499bfb6 100644 (file)
@@ -18,6 +18,7 @@
 #include "ConfigSource.h"
 #include "FileConfigSource.h"
 #include "ConfigValue.h"
+#include "ConfigCache.h"
 
 #define CONF_NONE       0
 #define CONF_ROM        1
 #define config_set_command_checksum        CHECKSUM("config-set")
 #define config_load_command_checksum       CHECKSUM("config-load")
 
-void Configurator::on_module_loaded(){
+void Configurator::on_module_loaded()
+{
     this->register_for_event(ON_CONSOLE_LINE_RECEIVED);
-//    this->register_for_event(ON_GCODE_RECEIVED);
-//    this->register_for_event(ON_MAIN_LOOP);
+    //    this->register_for_event(ON_GCODE_RECEIVED);
+    //    this->register_for_event(ON_MAIN_LOOP);
 }
 
 // When a new line is received, check if it is a command, and if it is, act upon it
-void Configurator::on_console_line_received( void* argument ){
-    SerialMessage new_message = *static_cast<SerialMessage*>(argument);
+void Configurator::on_console_line_received( void *argument )
+{
+    SerialMessage new_message = *static_cast<SerialMessage *>(argument);
 
     // ignore comments
     if(new_message.message[0] == ';') return;
@@ -44,7 +47,7 @@ void Configurator::on_console_line_received( void* argument ){
     string possible_command = new_message.message;
 
     // We don't compare to a string but to a checksum of that string, this saves some space in flash memory
-    uint16_t check_sum = get_checksum( possible_command.substr(0,possible_command.find_first_of(" \r\n")) );  // todo: put this method somewhere more convenient
+    uint16_t check_sum = get_checksum( possible_command.substr(0, possible_command.find_first_of(" \r\n")) ); // todo: put this method somewhere more convenient
 
     // Act depending on command
     if (check_sum == config_get_command_checksum)
@@ -56,50 +59,52 @@ void Configurator::on_console_line_received( void* argument ){
 }
 
 // Process and respond to eeprom gcodes (M50x)
-void Configurator::on_gcode_received(void* argument){
-    Gcode* gcode = static_cast<Gcode*>(argument);
-    if( gcode->has_letter('G') ){
+void Configurator::on_gcode_received(void *argument)
+{
+    Gcode *gcode = static_cast<Gcode *>(argument);
+    if( gcode->has_letter('G') ) {
         int code = gcode->get_value('G');
-        switch( code ){
+        switch( code ) {
         }
-    }
-    else if( gcode->has_letter('M') ){
+    } else if( gcode->has_letter('M') ) {
         int code = gcode->get_value('M');
-        switch( code ){
+        switch( code ) {
         }
     }
 }
 
-void Configurator::on_main_loop(void* argument){}
+void Configurator::on_main_loop(void *argument) {}
 
 // Output a ConfigValue from the specified ConfigSource to the stream
-void Configurator::config_get_command( string parameters, StreamOutput* stream ){
+void Configurator::config_get_command( string parameters, StreamOutput *stream )
+{
     string source = shift_parameter(parameters);
     string setting = shift_parameter(parameters);
-    if (setting == "") { // output live setting
+    if (setting == "") { // output settings from the config-cache
         setting = source;
         source = "";
         uint16_t setting_checksums[3];
         get_checksums(setting_checksums, setting );
-        ConfigValue* cv = THEKERNEL->config->value(setting_checksums);
-        string value = "";
-        if(cv->found){
-            value = cv->as_string();
-            stream->printf( "live: %s is set to %s\r\n", setting.c_str(), value.c_str() );
-        }else{
-            stream->printf( "live: %s is not in config\r\n", setting.c_str());
+        THEKERNEL->config->config_cache_load(); // need to load config cache first as it is unloaded after booting
+        ConfigValue *cv = THEKERNEL->config->value(setting_checksums);
+        if(cv != NULL && cv->found) {
+            string value = cv->as_string();
+            stream->printf( "cached: %s is set to %s\r\n", setting.c_str(), value.c_str() );
+        } else {
+            stream->printf( "cached: %s is not in config\r\n", setting.c_str());
         }
+        THEKERNEL->config->config_cache_clear();
 
-    } else { // output setting from specified source
+    } else { // output setting from specified source by parsing the config file
         uint16_t source_checksum = get_checksum( source );
         uint16_t setting_checksums[3];
         get_checksums(setting_checksums, setting );
-        for(unsigned int i=0; i < THEKERNEL->config->config_sources.size(); i++){
-            if( THEKERNEL->config->config_sources[i]->is_named(source_checksum) ){
+        for(unsigned int i = 0; i < THEKERNEL->config->config_sources.size(); i++) {
+            if( THEKERNEL->config->config_sources[i]->is_named(source_checksum) ) {
                 string value = THEKERNEL->config->config_sources[i]->read(setting_checksums);
-                if(value.empty()){
+                if(value.empty()) {
                     stream->printf( "%s: %s is not in config\r\n", source.c_str(), setting.c_str() );
-                }else{
+                } else {
                     stream->printf( "%s: %s is set to %s\r\n", source.c_str(), setting.c_str(), value.c_str() );
                 }
                 break;
@@ -109,21 +114,22 @@ void Configurator::config_get_command( string parameters, StreamOutput* stream )
 }
 
 // Write the specified setting to the specified ConfigSource
-void Configurator::config_set_command( string parameters, StreamOutput* stream ){
+void Configurator::config_set_command( string parameters, StreamOutput *stream )
+{
     string source = shift_parameter(parameters);
     string setting = shift_parameter(parameters);
     string value = shift_parameter(parameters);
-    if(source.empty() || setting.empty()|| value.empty()) {
+    if(source.empty() || setting.empty() || value.empty()) {
         stream->printf( "Usage: config-set source setting value # where source is sd, setting is the key and value is the new value\r\n" );
         return;
     }
 
     uint16_t source_checksum = get_checksum(source);
-    for(unsigned int i=0; i < THEKERNEL->config->config_sources.size(); i++){
-        if( THEKERNEL->config->config_sources[i]->is_named(source_checksum) ){
+    for(unsigned int i = 0; i < THEKERNEL->config->config_sources.size(); i++) {
+        if( THEKERNEL->config->config_sources[i]->is_named(source_checksum) ) {
             if(THEKERNEL->config->config_sources[i]->write(setting, value)) {
                 stream->printf( "%s: %s has been set to %s\r\n", source.c_str(), setting.c_str(), value.c_str() );
-            }else{
+            } else {
                 stream->printf( "%s: %s not enough space to overwrite existing key/value\r\n", source.c_str(), setting.c_str() );
             }
             return;
@@ -145,25 +151,53 @@ void Configurator::config_set_command( string parameters, StreamOutput* stream )
     */
 }
 
-// Reload config values from the specified ConfigSource
-void Configurator::config_load_command( string parameters, StreamOutput* stream ){
+// Reload config values from the specified ConfigSource, NOTE this probably does not work anymore
+// also used for debugging by dumping the config-cache
+void Configurator::config_load_command( string parameters, StreamOutput *stream )
+{
     string source = shift_parameter(parameters);
-    if(source == ""){
+    if(source == "load") {
+        THEKERNEL->config->config_cache_load();
+        stream->printf( "config cache loaded\r\n" );
+
+    } else if(source == "unload") {
+        THEKERNEL->config->config_cache_clear();
+        stream->printf( "config cache unloaded\r\n" );
+
+    } else if(source == "dump") {
+        THEKERNEL->config->config_cache_load();
+        THEKERNEL->config->config_cache->dump(stream);
+        THEKERNEL->config->config_cache_clear();
+
+    } else if(source == "checksum") {
+        string key = shift_parameter(parameters);
+        uint16_t cs[3];
+        get_checksums(cs, key);
+        stream->printf( "checksum of %s = %02X %02X %02X\n", key.c_str(), cs[0], cs[1], cs[2]);
+
+    } else if(source == "") {
         THEKERNEL->config->config_cache_load();
         THEKERNEL->call_event(ON_CONFIG_RELOAD);
         stream->printf( "Reloaded settings\r\n" );
-    } else if(file_exists(source)){
+        THEKERNEL->config->config_cache_clear();
+
+    } else if(file_exists(source)) {
         FileConfigSource fcs(source, "userfile");
-        fcs.transfer_values_to_cache(&THEKERNEL->config->config_cache);
+        THEKERNEL->config->config_cache_load(false);
+        fcs.transfer_values_to_cache(THEKERNEL->config->config_cache);
         THEKERNEL->call_event(ON_CONFIG_RELOAD);
         stream->printf( "Loaded settings from %s\r\n", source.c_str() );
+        THEKERNEL->config->config_cache_clear();
+
     } else {
         uint16_t source_checksum = get_checksum(source);
-        for(unsigned int i=0; i < THEKERNEL->config->config_sources.size(); i++){
-            if( THEKERNEL->config->config_sources[i]->is_named(source_checksum) ){
-                THEKERNEL->config->config_sources[i]->transfer_values_to_cache(&THEKERNEL->config->config_cache);
+        for(unsigned int i = 0; i < THEKERNEL->config->config_sources.size(); i++) {
+            if( THEKERNEL->config->config_sources[i]->is_named(source_checksum) ) {
+                THEKERNEL->config->config_cache_load(false);
+                THEKERNEL->config->config_sources[i]->transfer_values_to_cache(THEKERNEL->config->config_cache);
                 THEKERNEL->call_event(ON_CONFIG_RELOAD);
                 stream->printf( "Loaded settings from %s\r\n", source.c_str() );
+                THEKERNEL->config->config_cache_clear();
                 break;
             }
         }