Selaa lähdekoodia

ncd: add NCDModuleIndex to find modules faster

ambrop7 14 vuotta sitten
vanhempi
sitoutus
0325c73684

+ 1 - 0
blog_channels.txt

@@ -93,3 +93,4 @@ BSSLConnection 4
 BDatagram 4
 PeerChat 4
 BArpProbe 4
+NCDModuleIndex 4

+ 4 - 0
generated/blog_channel_NCDModuleIndex.h

@@ -0,0 +1,4 @@
+#ifdef BLOG_CURRENT_CHANNEL
+#undef BLOG_CURRENT_CHANNEL
+#endif
+#define BLOG_CURRENT_CHANNEL BLOG_CHANNEL_NCDModuleIndex

+ 2 - 1
generated/blog_channels_defines.h

@@ -93,4 +93,5 @@
 #define BLOG_CHANNEL_BDatagram 92
 #define BLOG_CHANNEL_PeerChat 93
 #define BLOG_CHANNEL_BArpProbe 94
-#define BLOG_NUM_CHANNELS 95
+#define BLOG_CHANNEL_NCDModuleIndex 95
+#define BLOG_NUM_CHANNELS 96

+ 1 - 0
generated/blog_channels_list.h

@@ -93,3 +93,4 @@
 {.name = "BDatagram", .loglevel = 4},
 {.name = "PeerChat", .loglevel = 4},
 {.name = "BArpProbe", .loglevel = 4},
+{.name = "NCDModuleIndex", .loglevel = 4},

+ 1 - 0
ncd/CMakeLists.txt

@@ -32,6 +32,7 @@ add_executable(badvpn-ncd
     ncd.c
     NCDValue.c
     NCDModule.c
+    NCDModuleIndex.c
     NCDIfConfig.c
     NCDInterfaceMonitor.c
     BEventLock.c

+ 116 - 0
ncd/NCDModuleIndex.c

@@ -0,0 +1,116 @@
+/**
+ * @file NCDModuleIndex.c
+ * @author Ambroz Bizjak <ambrop7@gmail.com>
+ * 
+ * @section LICENSE
+ * 
+ * This file is part of BadVPN.
+ * 
+ * BadVPN is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ * 
+ * BadVPN 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <misc/offset.h>
+#include <base/BLog.h>
+
+#include "NCDModuleIndex.h"
+
+#include <generated/blog_channel_NCDModuleIndex.h>
+
+static int string_comparator (void *user, const char *s1, const char *s2)
+{
+    int cmp = strcmp(s1, s2);
+    if (cmp < 0) {
+        return -1;
+    }
+    if (cmp > 0) {
+        return 1;
+    }
+    return 0;
+}
+
+static struct NCDModuleIndex_module * find_module (NCDModuleIndex *o, const char *type)
+{
+    BAVLNode *node = BAVL_LookupExact(&o->modules_tree, (void *)type);
+    if (!node) {
+        return NULL;
+    }
+    
+    struct NCDModuleIndex_module *m = UPPER_OBJECT(node, struct NCDModuleIndex_module, modules_tree_node);
+    ASSERT(!strcmp(m->type, type))
+    
+    return m;
+}
+
+void NCDModuleIndex_Init (NCDModuleIndex *o)
+{
+    // init modules tree
+    BAVL_Init(&o->modules_tree, OFFSET_DIFF(struct NCDModuleIndex_module, type, modules_tree_node), (BAVL_comparator)string_comparator, NULL);
+    
+    DebugObject_Init(&o->d_obj);
+}
+
+void NCDModuleIndex_Free (NCDModuleIndex *o)
+{
+    DebugObject_Free(&o->d_obj);
+    
+    while (!BAVL_IsEmpty(&o->modules_tree)) {
+        struct NCDModuleIndex_module *m = UPPER_OBJECT(BAVL_GetFirst(&o->modules_tree), struct NCDModuleIndex_module, modules_tree_node);
+        BAVL_Remove(&o->modules_tree, &m->modules_tree_node);
+        free(m);
+    }
+}
+
+int NCDModuleIndex_AddGroup (NCDModuleIndex *o, const struct NCDModuleGroup *group)
+{
+    DebugObject_Access(&o->d_obj);
+    
+    for (const struct NCDModule *nm = group->modules; nm->type; nm++) {
+        if (find_module(o, nm->type)) {
+            BLog(BLOG_ERROR, "module type '%s' already exists", nm->type);
+            return 0;
+        }
+        
+        if (strlen(nm->type) > NCDMODULEINDEX_MAX_TYPE_LEN) {
+            BLog(BLOG_ERROR, "module type '%s' is too long", nm->type);
+            return 0;
+        }
+        
+        struct NCDModuleIndex_module *m = malloc(sizeof(*m));
+        if (!m) {
+            BLog(BLOG_ERROR, "malloc failed");
+            return 0;
+        }
+        
+        strcpy(m->type, nm->type);
+        m->module = nm;
+        ASSERT_EXECUTE(BAVL_Insert(&o->modules_tree, &m->modules_tree_node, NULL))
+    }
+    
+    return 1;
+}
+
+const struct NCDModule * NCDModuleIndex_FindModule (NCDModuleIndex *o, const char *type)
+{
+    DebugObject_Access(&o->d_obj);
+    
+    struct NCDModuleIndex_module *m = find_module(o, type);
+    if (!m) {
+        return NULL;
+    }
+    
+    return m->module;
+}

+ 49 - 0
ncd/NCDModuleIndex.h

@@ -0,0 +1,49 @@
+/**
+ * @file NCDModuleIndex.h
+ * @author Ambroz Bizjak <ambrop7@gmail.com>
+ * 
+ * @section LICENSE
+ * 
+ * This file is part of BadVPN.
+ * 
+ * BadVPN is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ * 
+ * BadVPN 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef BADVPN_NCDMODULEINDEX_H
+#define BADVPN_NCDMODULEINDEX_H
+
+#include <misc/debug.h>
+#include <structure/BAVL.h>
+#include <base/DebugObject.h>
+#include <ncd/NCDModule.h>
+
+#define NCDMODULEINDEX_MAX_TYPE_LEN 64
+
+typedef struct {
+    BAVL modules_tree;
+    DebugObject d_obj;
+} NCDModuleIndex;
+
+struct NCDModuleIndex_module {
+    char type[NCDMODULEINDEX_MAX_TYPE_LEN + 1];
+    const struct NCDModule *module;
+    BAVLNode modules_tree_node;
+};
+
+void NCDModuleIndex_Init (NCDModuleIndex *o);
+void NCDModuleIndex_Free (NCDModuleIndex *o);
+int NCDModuleIndex_AddGroup (NCDModuleIndex *o, const struct NCDModuleGroup *group) WARN_UNUSED;
+const struct NCDModule * NCDModuleIndex_FindModule (NCDModuleIndex *o, const char *type);
+
+#endif

+ 19 - 15
ncd/ncd.c

@@ -45,6 +45,7 @@
 #include <udevmonitor/NCDUdevManager.h>
 #include <ncd/NCDConfigParser.h>
 #include <ncd/NCDModule.h>
+#include <ncd/NCDModuleIndex.h>
 #include <ncd/modules/modules.h>
 
 #ifndef BADVPN_USE_WINAPI
@@ -147,6 +148,9 @@ BProcessManager manager;
 // udev manager
 NCDUdevManager umanager;
 
+// module index
+NCDModuleIndex mindex;
+
 // config AST
 struct NCDConfig_processes *config_ast;
 
@@ -157,7 +161,6 @@ static void print_help (const char *name);
 static void print_version (void);
 static int parse_arguments (int argc, char *argv[]);
 static void signal_handler (void *unused);
-static const struct NCDModule * find_module (const char *name);
 static int arg_value_init_string (struct arg_value *o, const char *string);
 static int arg_value_init_variable (struct arg_value *o, const char *variable);
 static void arg_value_init_list (struct arg_value *o);
@@ -278,6 +281,17 @@ int main (int argc, char **argv)
     // init udev manager
     NCDUdevManager_Init(&umanager, &ss, &manager);
     
+    // init module index
+    NCDModuleIndex_Init(&mindex);
+    
+    // add module groups to index
+    for (const struct NCDModuleGroup **g = ncd_modules; *g; g++) {
+        if (!NCDModuleIndex_AddGroup(&mindex, *g)) {
+            BLog(BLOG_ERROR, "NCDModuleIndex_AddGroup failed");
+            goto fail2;
+        }
+    }
+    
     // setup signal handler
     if (!BSignal_Init(&ss, signal_handler, NULL)) {
         BLog(BLOG_ERROR, "BSignal_Init failed");
@@ -355,6 +369,9 @@ fail3:
     // remove signal handler
     BSignal_Finish();
 fail2:
+    // free module index
+    NCDModuleIndex_Free(&mindex);
+    
     // free udev manager
     NCDUdevManager_Free(&umanager);
     
@@ -563,19 +580,6 @@ void signal_handler (void *unused)
     }
 }
 
-const struct NCDModule * find_module (const char *name)
-{
-    for (const struct NCDModuleGroup **g = ncd_modules; *g; g++) {
-        for (const struct NCDModule *m = (*g)->modules; m->type; m++) {
-            if (!strcmp(m->type, name)) {
-                return m;
-            }
-        }
-    }
-    
-    return NULL;
-}
-
 int arg_value_init_string (struct arg_value *o, const char *string)
 {
     o->type = ARG_VALUE_TYPE_STRING;
@@ -1151,7 +1155,7 @@ void process_advance_job_handler (struct process *p)
     }
     
     // find module to instantiate
-    if (!(ps->module = find_module(type))) {
+    if (!(ps->module = NCDModuleIndex_FindModule(&mindex, type))) {
         process_statement_log(ps, BLOG_ERROR, "failed to find module: %s", type);
         goto fail1;
     }