This is what I have mentioned earlier this day. This introduces a
CONFIG_VERSION define, which is used to represent a certain config file
format. Every time we change config fle format (adding features, moving things
around), we bump this number. This makes easy to determine, that somebody is
using an outdated config file and that it just might not work.

Why such thing? We're using a 'pull' model. We pickup what we need from config
virtually ignoring everything else. This is not like HTTP Server, where every
configuration directive must make sense, or the web server won't even start.
In addition, when some element is missing we asume some reasonable default. So
it is possible that running old config against new release of flood which uses
new config file format, will produce bad results or no results at all. So we
bump CONFIG_VERSION define every time we introduce new feature, or change
config file structure. Running such new flood release against old config
files would produce a warning, to keep user aware of the problem. If this
patch gets accepted, I'll update all config files to config version 1.0.

This brings up another problem. We don't really have config file, but data
mixed with config. The config part (farm, farmer and profile) is the easy
stuff, but the data part (url's) might just be a large block of characters. We
can't just say: ohh... we moved some attributes around, please rewrite your
urllist from scratch. So we have to come up with some tool to convert one file
format to another, when big changes will come. I think since we're in XML
world, an stylesheet would be the best solution.

Another benefit of having versioned config files, is that when we'll have a
bunch of 'URL grabbing apps' (my 'Flood URL Bag' is just around the corner :)
it would be extremally helpfull, to know what config file format to output.
Such applications would probably have their own development cycle, outside
flood repository, so they can't really stay in sync with flood.

Anyway... this is how I see it. Please review it and yell if you find
something, that is really obscure.

regards,
Jacek Prucia

diff -urN flood.orig/config.h.in flood/config.h.in
--- flood.orig/config.h.in      2003-08-09 23:23:51.000000000 +0200
+++ flood/config.h.in   2003-08-10 13:53:14.000000000 +0200
@@ -8,6 +8,8 @@
 #define FLOOD_STRLEN_MAX 256
 
 /* XML symbolic roots to the various objects we define. */
+#define XML_FLOOD "flood"
+#define XML_FLOOD_VERSION "version"
 #define XML_SEED "seed"
 #define XML_URLLIST "urllist"
 #define XML_URLLIST_SEQUENCE "sequence"
@@ -51,6 +53,7 @@
 #define XML_ELEM_DELIM "."
 
 #define FLOOD_VERSION "1.1-dev"
+#define CONFIG_VERSION "1.0"
 
 #define CRLF "\r\n"
 
diff -urN flood.orig/flood.c flood/flood.c
--- flood.orig/flood.c  2003-08-09 09:33:27.000000000 +0200
+++ flood/flood.c       2003-08-10 13:57:13.000000000 +0200
@@ -127,6 +127,50 @@
     return APR_SUCCESS;
 }
 
+/* check if config file version matches flood config version */
+static apr_status_t check_versions(config_t *config)
+{
+    apr_status_t stat;
+    char *endptr = NULL;
+    float flood_version = 0;
+    float config_version = 1.0;
+    struct apr_xml_elem *root_elem;
+
+    /* we assume that CONFIG_VERSION is sane */
+    flood_version = strtof(CONFIG_VERSION, NULL);
+
+    /* get the root element */
+    if ((stat = retrieve_root_xml_elem(&root_elem, config)) != APR_SUCCESS) {
+        return stat;
+    }
+
+    if (root_elem->attr) {
+        apr_xml_attr *attr = root_elem->attr;
+        while (attr) {
+            if (!strncasecmp(attr->name, XML_FLOOD_VERSION,
+                            FLOOD_STRLEN_MAX)) {
+                config_version = strtof(attr->value, &endptr);
+                if (*endptr != '\0') {
+                    apr_file_printf(local_stderr,
+                                    "invalid config version '%s'.\n",
+                                    attr->value);
+                    return APR_EGENERAL;
+                }
+            }
+            attr = attr->next;
+        }
+    }
+
+    if (conf_version != flood_version) {
+        apr_file_printf(local_stderr,
+                        "your config file version '%.1f' doesn't match flood 
config version '%.1f'.\n",
+                        config_version, flood_version);
+    }
+
+    return APR_SUCCESS;
+
+}
+
 int main(int argc, char** argv)
 {
     apr_status_t stat;
@@ -172,6 +216,10 @@
         exit(-1);
     }
 
+    if ((stat = check_versions(config)) != APR_SUCCESS) {
+        exit(-1);
+    }
+
     if ((stat = run_farm(config, "Bingo", local_pool)) != APR_SUCCESS) {
         char buf[256];
         apr_strerror(stat, (char*) &buf, 256);

Reply via email to