Merge branch 'collectd-4.5'
[collectd.git] / src / filter_chain.c
index 5784426..01cd224 100644 (file)
@@ -91,9 +91,9 @@ struct fc_target_s
 }; /* }}} */
 
 /* List of rules, used in fc_chain_t */
-struct fc_fule_s;
-typedef struct fc_fule_s fc_rule_t; /* {{{ */
-struct fc_fule_s
+struct fc_rule_s;
+typedef struct fc_rule_s fc_rule_t; /* {{{ */
+struct fc_rule_s
 {
   char name[DATA_MAX_NAME_LEN];
   fc_match_t  *matches;
@@ -340,17 +340,23 @@ static int fc_config_add_target (fc_target_t **targets_head, /* {{{ */
 
   sstrncpy (t->name, ptr->name, sizeof (t->name));
   memcpy (&t->proc, &ptr->proc, sizeof (t->proc));
-  assert (t->proc.create != NULL);
   t->user_data = NULL;
   t->next = NULL;
 
-  status = (*t->proc.create) (ci, &t->user_data);
-  if (status != 0)
+  if (t->proc.create != NULL)
   {
-    WARNING ("Filter subsystem: Failed to create a %s match.",
-        t->name);
-    fc_free_targets (t);
-    return (-1);
+    status = (*t->proc.create) (ci, &t->user_data);
+    if (status != 0)
+    {
+      WARNING ("Filter subsystem: Failed to create a %s match.",
+          t->name);
+      fc_free_targets (t);
+      return (-1);
+    }
+  }
+  else
+  {
+    t->user_data = NULL;
   }
   
   if (*targets_head != NULL)
@@ -559,12 +565,19 @@ int fc_process_chain (const data_set_t *ds, value_list_t *vl, /* {{{ */
   if (chain == NULL)
     return (-1);
 
-  status = FC_ACTION_CONTINUE;
+  DEBUG ("fc_process_chain (chain = %s);", chain->name);
 
+  status = FC_TARGET_CONTINUE;
   for (rule = chain->rules; rule != NULL; rule = rule->next)
   {
     fc_match_t *match;
 
+    if (rule->name[0] != 0)
+    {
+      DEBUG ("fc_process_chain (%s): Testing the `%s' rule.",
+          chain->name, rule->name);
+    }
+
     /* N. B.: rule->matches may be NULL. */
     for (match = rule->matches; match != NULL; match = match->next)
     {
@@ -572,7 +585,7 @@ int fc_process_chain (const data_set_t *ds, value_list_t *vl, /* {{{ */
           &match->user_data);
       if (status < 0)
       {
-        WARNING ("fc_process: A match failed.");
+        WARNING ("fc_process_chain (%s): A match failed.", chain->name);
         break;
       }
       else if (status != FC_MATCH_MATCHES)
@@ -581,48 +594,116 @@ int fc_process_chain (const data_set_t *ds, value_list_t *vl, /* {{{ */
 
     /* for-loop has been aborted: Either error or no match. */
     if (match != NULL)
+    {
+      status = FC_TARGET_CONTINUE;
       continue;
+    }
+
+    if (rule->name[0] != 0)
+    {
+      DEBUG ("fc_process_chain (%s): Rule `%s' matches.",
+          chain->name, rule->name);
+    }
 
     for (target = rule->targets; target != NULL; target = target->next)
     {
-      /* If we get here, all matches have matched the value. Execute the target. */
+      /* If we get here, all matches have matched the value. Execute the
+       * target. */
       status = (*target->proc.invoke) (ds, vl, /* meta = */ NULL,
           &target->user_data);
       if (status < 0)
       {
-        WARNING ("fc_process: A target failed.");
+        WARNING ("fc_process_chain (%s): A target failed.", chain->name);
         continue;
       }
-      else if (status == FC_ACTION_CONTINUE)
+      else if (status == FC_TARGET_CONTINUE)
         continue;
-      else if (status == FC_ACTION_STOP)
+      else if (status == FC_TARGET_STOP)
+        break;
+      else if (status == FC_TARGET_RETURN)
         break;
       else
       {
-        WARNING ("fc_process: Unknown target return value: %i", status);
+        WARNING ("fc_process_chain (%s): Unknown return value "
+            "from target `%s': %i",
+            chain->name, target->name, status);
       }
     }
 
-    if (status == FC_ACTION_STOP)
+    if ((status == FC_TARGET_STOP)
+        || (status == FC_TARGET_RETURN))
+    {
+      if (rule->name[0] != 0)
+      {
+        DEBUG ("fc_process_chain (%s): Rule `%s' signaled "
+            "the %s condition.",
+            chain->name, rule->name,
+            (status == FC_TARGET_STOP) ? "stop" : "return");
+      }
       break;
+    }
+    else
+    {
+      status = FC_TARGET_CONTINUE;
+    }
   } /* for (rule) */
 
-  /* for-loop has been aborted: A target returned `FC_ACTION_STOP' */
+  if (status == FC_TARGET_STOP)
+    return (FC_TARGET_STOP);
+  else if (status == FC_TARGET_RETURN)
+    return (FC_TARGET_CONTINUE);
+
+  /* for-loop has been aborted: A target returned `FC_TARGET_STOP' */
   if (rule != NULL)
-    return (0);
+    return (FC_TARGET_CONTINUE);
 
+  DEBUG ("fc_process_chain (%s): Executing the default targets.",
+      chain->name);
+
+  status = FC_TARGET_CONTINUE;
   for (target = chain->targets; target != NULL; target = target->next)
   {
-    /* If we get here, all matches have matched the value. Execute the target. */
+    /* If we get here, all matches have matched the value. Execute the
+     * target. */
     status = (*target->proc.invoke) (ds, vl, /* meta = */ NULL,
         &target->user_data);
     if (status < 0)
     {
-      WARNING ("fc_process: The default target failed.");
+      WARNING ("fc_process_chain (%s): The default target failed.",
+          chain->name);
+    }
+    else if (status == FC_TARGET_CONTINUE)
+      continue;
+    else if (status == FC_TARGET_STOP)
+      break;
+    else if (status == FC_TARGET_RETURN)
+      break;
+    else
+    {
+      WARNING ("fc_process_chain (%s): Unknown return value "
+          "from target `%s': %i",
+          chain->name, target->name, status);
     }
   }
 
-  return (0);
+  if ((status == FC_TARGET_STOP)
+      || (status == FC_TARGET_RETURN))
+  {
+    assert (target != NULL);
+    DEBUG ("fc_process_chain (%s): Default target `%s' signaled "
+        "the %s condition.",
+        chain->name, target->name,
+        (status == FC_TARGET_STOP) ? "stop" : "return");
+    if (status == FC_TARGET_STOP)
+      return (FC_TARGET_STOP);
+    else
+      return (FC_TARGET_CONTINUE);
+  }
+
+  DEBUG ("fc_process_chain (%s): Signaling `continue' at end of chain.",
+      chain->name);
+
+  return (FC_TARGET_CONTINUE);
 } /* }}} int fc_process_chain */
 
 /*
@@ -703,16 +784,24 @@ static int fc_bit_jump_invoke (const data_set_t *ds, /* {{{ */
   status = fc_process_chain (ds, vl, chain);
   if (status < 0)
     return (status);
-
-  return (FC_ACTION_CONTINUE);
+  else if (status == FC_TARGET_STOP)
+    return (FC_TARGET_STOP);
+  else
+    return (FC_TARGET_CONTINUE);
 } /* }}} int fc_bit_jump_invoke */
 
 static int fc_bit_stop_invoke (const data_set_t *ds, /* {{{ */
     value_list_t *vl, notification_meta_t **meta, void **user_data)
 {
-  return (FC_ACTION_STOP);
+  return (FC_TARGET_STOP);
 } /* }}} int fc_bit_stop_invoke */
 
+static int fc_bit_return_invoke (const data_set_t *ds, /* {{{ */
+    value_list_t *vl, notification_meta_t **meta, void **user_data)
+{
+  return (FC_TARGET_RETURN);
+} /* }}} int fc_bit_return_invoke */
+
 static int fc_bit_write_create (const oconfig_item_t *ci, /* {{{ */
     void **user_data)
 {
@@ -823,7 +912,7 @@ static int fc_bit_write_invoke (const data_set_t *ds, /* {{{ */
     } /* for (i = 0; plugin_list[i] != NULL; i++) */
   }
 
-  return (FC_ACTION_CONTINUE);
+  return (FC_TARGET_CONTINUE);
 } /* }}} int fc_bit_write_invoke */
 
 static int fc_init_once (void) /* {{{ */
@@ -847,6 +936,12 @@ static int fc_init_once (void) /* {{{ */
   fc_register_target ("stop", tproc);
 
   memset (&tproc, 0, sizeof (tproc));
+  tproc.create  = NULL;
+  tproc.destroy = NULL;
+  tproc.invoke  = fc_bit_return_invoke;
+  fc_register_target ("return", tproc);
+
+  memset (&tproc, 0, sizeof (tproc));
   tproc.create  = fc_bit_write_create;
   tproc.destroy = fc_bit_write_destroy;
   tproc.invoke  = fc_bit_write_invoke;
@@ -864,6 +959,8 @@ int fc_register_match (const char *name, match_proc_t proc) /* {{{ */
 {
   fc_match_t *m;
 
+  DEBUG ("fc_register_match (%s);", name);
+
   m = (fc_match_t *) malloc (sizeof (*m));
   if (m == NULL)
     return (-ENOMEM);
@@ -896,6 +993,8 @@ int fc_register_target (const char *name, target_proc_t proc) /* {{{ */
 {
   fc_target_t *t;
 
+  DEBUG ("fc_register_target (%s);", name);
+
   t = (fc_target_t *) malloc (sizeof (*t));
   if (t == NULL)
     return (-ENOMEM);
@@ -936,9 +1035,8 @@ int fc_process (const data_set_t *ds, value_list_t *vl) /* {{{ */
   if (chain != NULL)
     return (fc_process_chain (ds, vl, chain));
 
-  ERROR ("fc_process: TODO: Implement default behavior!");
-
-  return (0);
+  return (fc_bit_write_invoke (ds, vl,
+        /* meta = */ NULL, /* user_data = */ NULL));
 } /* }}} int fc_process */
 
 int fc_configure (const oconfig_item_t *ci) /* {{{ */