MEDIUM: sample: add trie support to 51Degrees
authorThomas Holmes <tom@51degrees.com>
Fri, 29 May 2015 11:54:25 +0000 (12:54 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 2 Jun 2015 17:30:53 +0000 (19:30 +0200)
Trie or pattern algorithm is used depending on what 51Degrees source
files are provided to MAKE.

include/types/global.h
src/cfgparse.c
src/haproxy.c
src/sample.c

index 2203a1f..b3b9672 100644 (file)
@@ -186,10 +186,13 @@ struct global {
 #endif
 
 #ifdef USE_51DEGREES
-       fiftyoneDegreesDataSet _51d_data_set;
-       char * _51d_data_file_path;       /* the path of the data file. this is taken from 51degrees-data-file in config. */
        char _51d_property_seperator;    /* the seperator to use in the response for the values. this is taken from 51degrees-property-seperator from config. */
        struct list _51d_property_names; /* list of properties to load into the data set. this is taken from 51degrees-property-name-list from config. */
+       char * _51d_data_file_path;
+#ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED
+       fiftyoneDegreesDataSet _51d_data_set; /* data set used with the pattern detection method. */
+#endif
+
 #endif
 };
 
index 44b1c2c..30d51c7 100644 (file)
@@ -1752,7 +1752,7 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
 #ifdef USE_51DEGREES
        else if (strcmp(args[0], "51degrees-data-file") == 0) {
                if(!*(args[1])) {
-                       Alert("parsing [%s:%d]: '%s' expects a filepath to a 51Degrees data file.\n", file, linenum, args[0]);
+                       Alert("parsing [%s:%d]: '%s' expects a filepath to a 51Degrees trie or pattern data file.\n", file, linenum, args[0]);
                        err_code |= ERR_ALERT | ERR_FATAL;
                        goto out;
                }
@@ -1760,12 +1760,12 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
        }
        else if (strcmp(args[0], "51degrees-property-seperator") == 0) {
                if(!*(args[1])) {
-                       Alert("parsing [%s:%d]: '%s' expects a ingle character.\n", file, linenum, args[0]);
+                       Alert("parsing [%s:%d]: '%s' expects a single character.\n", file, linenum, args[0]);
                        err_code |= ERR_ALERT | ERR_FATAL;
                        goto out;
                }
                if (strlen(args[1]) > 1) {
-                       Alert("parsing [%s:%d]: '%s' expects a ingle character, got '%s'.\n", file, linenum, args[0], args[1]);
+                       Alert("parsing [%s:%d]: '%s' expects a single character, got '%s'.\n", file, linenum, args[0], args[1]);
                        err_code |= ERR_ALERT | ERR_FATAL;
                        goto out;
                }
index daf68d0..e04aa3f 100644 (file)
@@ -548,8 +548,8 @@ void init(int argc, char **argv)
 #ifdef USE_51DEGREES
        int i = 0;
        struct _51d_property_names *name;
-       fiftyoneDegreesDataSetInitStatus _51d_dataset_status;
        char **_51d_property_list;
+       fiftyoneDegreesDataSetInitStatus _51d_dataset_status = DATA_SET_INIT_STATUS_NOT_SET;
 #endif
 
        chunk_init(&trash, malloc(global.tune.bufsize), global.tune.bufsize);
@@ -1108,9 +1108,14 @@ void init(int argc, char **argv)
        list_for_each_entry(name, &global._51d_property_names, list)
                _51d_property_list[i++] = name->name;
 
+#ifdef FIFTYONEDEGREES_H_TRIE_INCLUDED
+       _51d_dataset_status = fiftyoneDegreesInitWithPropertyArray(global._51d_data_file_path, _51d_property_list, i);
+#endif
+#ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED
        _51d_dataset_status = fiftyoneDegreesInitWithPropertyArray(global._51d_data_file_path, &global._51d_data_set, _51d_property_list, i);
-       free(_51d_property_list);
+#endif
        chunk_reset(&trash);
+
        switch (_51d_dataset_status) {
                case DATA_SET_INIT_STATUS_SUCCESS:
                        break;
@@ -1118,23 +1123,37 @@ void init(int argc, char **argv)
                        chunk_printf(&trash, "Insufficient memory.");
                        break;
                case DATA_SET_INIT_STATUS_CORRUPT_DATA:
-                       chunk_printf(&trash, "Corrupt data.");
+#ifdef FIFTYONEDEGREES_H_TRIE_INCLUDED
+                       chunk_printf(&trash, "Corrupt data file. Check that the data file provided is uncompressed and Trie data format.");
+#endif
+#ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED
+                       chunk_printf(&trash, "Corrupt data file. Check that the data file provided is uncompressed and Pattern data format.");
+#endif
                        break;
                case DATA_SET_INIT_STATUS_INCORRECT_VERSION:
-                       chunk_printf(&trash, "Incorrect version.");
+#ifdef FIFTYONEDEGREES_H_TRIE_INCLUDED
+                       chunk_printf(&trash, "Incorrect version. Check that the data file provided is uncompressed and Trie data format.");
+#endif
+#ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED
+                       chunk_printf(&trash, "Incorrect version. Check that the data file provided is uncompressed and Pattern data format.");
+#endif
                        break;
                case DATA_SET_INIT_STATUS_FILE_NOT_FOUND:
                        chunk_printf(&trash, "File not found.");
                        break;
+               case DATA_SET_INIT_STATUS_NOT_SET:
+                       chunk_printf(&trash, "Data set not initialised.");
+                       break;
        }
        if (_51d_dataset_status != DATA_SET_INIT_STATUS_SUCCESS) {
                if (trash.len)
-                       Alert("51D Setup - Error reading 51Degrees data file: %s\n", trash.str);
+                       Alert("51Degrees Setup - Error reading 51Degrees data file. %s\n", trash.str);
                else
-                       Alert("51D Setup - Error reading 51Degrees data file.\n");
+                       Alert("51Degrees Setup - Error reading 51Degrees data file.\n");
                exit(1);
        }
-#endif
+       free(_51d_property_list);
+#endif // USE_51DEGREES
 }
 
 static void deinit_acl_cond(struct acl_cond *cond)
@@ -1488,13 +1507,18 @@ void deinit(void)
 #endif
 
 #ifdef USE_51DEGREES
+#ifdef FIFTYONEDEGREES_H_TRIE_INCLUDED
+       fiftyoneDegreesDestroy();
+#endif
+#ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED
        fiftyoneDegreesDestroy(&global._51d_data_set);
+#endif
        free(global._51d_data_file_path); global._51d_data_file_path = NULL;
        list_for_each_entry_safe(_51d_prop_name, _51d_prop_nameb, &global._51d_property_names, list) {
                LIST_DEL(&_51d_prop_name->list);
                free(_51d_prop_name);
        }
-#endif
+#endif // USE_51DEGREES
 
        free(global.log_send_hostname); global.log_send_hostname = NULL;
        free(global.log_tag); global.log_tag = NULL;
index 6418be8..1993255 100644 (file)
@@ -2130,13 +2130,64 @@ static int sample_conv_arith_even(const struct arg *arg_p,
 }
 
 #ifdef USE_51DEGREES
-static int fiftyone_degrees(const struct arg *args,
-                           struct sample *smp, void *private)
+#ifdef FIFTYONEDEGREES_H_TRIE_INCLUDED
+static int
+sample_fiftyone_degrees(const struct arg *args, struct sample *smp, void *private)
+{
+       int i; // used in loops.
+       int device_offset;
+       int property_index;
+       char no_data[] = "NoData"; // response when no data could be found.
+       struct chunk *tmp;
+
+       // use a temporary trash buffer and copy data in it
+       smp->data.str.str[smp->data.str.len] = '\0';
+
+       // perform detection.
+       device_offset = fiftyoneDegreesGetDeviceOffset(smp->data.str.str);
+
+       i = 0;
+       tmp = get_trash_chunk();
+       chunk_reset(tmp);
+
+       // loop through property names passed to the filter and fetch them from the dataset.
+       while (args[i].data.str.str) {
+               // try to find request property in dataset.
+               property_index = fiftyoneDegreesGetPropertyIndex(args[i].data.str.str);
+               if (property_index > 0) {
+                       chunk_appendf(tmp, "%s", fiftyoneDegreesGetValue(device_offset, property_index));
+               }
+               else {
+                       chunk_appendf(tmp, "%s", no_data);
+               }
+               // add seperator
+               if (global._51d_property_seperator)
+                       chunk_appendf(tmp, "%c", global._51d_property_seperator);
+               else
+                       chunk_appendf(tmp, ",");
+               ++i;
+       }
+
+       if (tmp->len) {
+               --tmp->len;
+               tmp->str[tmp->len] = '\0';
+       }
+
+       smp->data.str.str = tmp->str;
+       smp->data.str.len = strlen(smp->data.str.str);
+
+       return 1;
+}
+#endif // FIFTYONEDEGREES_H_TRIE_INCLUDED
+
+#ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED
+static int
+sample_fiftyone_degrees(const struct arg *args, struct sample *smp, void *private)
 {
        int i, j, found; // used in loops.
        fiftyoneDegreesWorkset* ws; // workset for detection.
        char no_data[] = "NoData"; // response when no data could be found.
-       struct _51d_property_names *property;
+       const char* property_name;
        struct chunk *tmp;
 
        // use a temporary trash buffer and copy data in it
@@ -2157,17 +2208,18 @@ static int fiftyone_degrees(const struct arg *args,
        while (args[i].data.str.str) {
                found = j = 0;
                // try to find request property in dataset.
-               list_for_each_entry(property, &global._51d_property_names, list) {
-                       if (strcmp(property->name, args[i].data.str.str) == 0) {
+               for (j = 0; j < ws->dataSet->requiredPropertyCount; j++) {
+                       property_name = fiftyoneDegreesGetPropertyName(ws->dataSet, ws->dataSet->requiredProperties[j]);
+                       if (strcmp(property_name, args[i].data.str.str) == 0) {
                                found = 1;
                                fiftyoneDegreesSetValues(ws, j);
                                chunk_appendf(tmp, "%s", fiftyoneDegreesGetValueName(ws->dataSet, *ws->values));
                                break;
                        }
-                       ++j;
                }
-               if (!found)
+               if (!found) {
                        chunk_appendf(tmp, "%s", no_data);
+               }
 
                // add seperator
                if (global._51d_property_seperator)
@@ -2189,7 +2241,8 @@ static int fiftyone_degrees(const struct arg *args,
 
        return 1;
 }
-#endif
+#endif // FIFTYONEDEGREES_H_PATTERN_INCLUDED
+#endif // USE_51DEGREES
 
 
 /************************************************************************/
@@ -2346,7 +2399,7 @@ static struct sample_conv_kw_list sample_conv_kws = {ILH, {
        { "mod",    sample_conv_arith_mod,  ARG1(1,UINT), NULL, SMP_T_UINT, SMP_T_UINT },
        { "neg",    sample_conv_arith_neg,             0, NULL, SMP_T_UINT, SMP_T_UINT },
 #ifdef USE_51DEGREES
-       { "51d",    fiftyone_degrees,       ARG5(1,STR,STR,STR,STR,STR), NULL, SMP_T_STR, SMP_T_STR },
+       { "51d",    sample_fiftyone_degrees,ARG5(1,STR,STR,STR,STR,STR), NULL, SMP_T_STR, SMP_T_STR },
 #endif
 
        { NULL, NULL, 0, 0, 0 },