dotnet plugin: Some work towards write callbacks.
authorFlorian Forster <octo@leeloo.lan.home.verplant.org>
Thu, 30 Dec 2010 07:15:27 +0000 (08:15 +0100)
committerFlorian Forster <octo@collectd.org>
Thu, 5 Apr 2012 08:22:03 +0000 (10:22 +0200)
bindings/csharp/collectd.cs
bindings/csharp/test.cs
src/dotnet.c

index 061c16d..c493799 100644 (file)
@@ -33,6 +33,7 @@ namespace CollectdAPI
 {
   public delegate int CollectdInitCallback ();
   public delegate int CollectdReadCallback ();
+  public delegate int CollectdWriteCallback (ValueList vl);
 
   public interface IValue /* {{{ */
   {
@@ -212,6 +213,29 @@ namespace CollectdAPI
       this._time = 0.0;
     }
 
+    internal ValueList (value_data_s vd,
+        int values_len, value_u[] values, int[] values_types)
+      :base (vd.host,
+          vd.plugin, vd.plugin_instance,
+          vd.type, vd.type_instance)
+    {
+      this._time = vd.time;
+      this._interval = vd.interval;
+
+      this._values = new ArrayList (values_len);
+      for (int i = 0; i < values_len; i++)
+      {
+        IValue iv;
+
+        if (values_types[i] == Collectd.DS_TYPE_GAUGE)
+          iv = new GaugeValue (values[i].gauge);
+        else
+          iv = new DeriveValue (values[i].derive);
+
+        this._values.Insert (i, iv);
+      }
+    }
+
     public ValueList (ValueList vl)
       :base (vl)
     {
@@ -304,10 +328,8 @@ namespace CollectdAPI
   } /* }}} struct value_u */
 
   [StructLayout (LayoutKind.Sequential)]
-  struct value_list_s /* {{{ */
+  struct value_data_s /* {{{ */
   {
-    public value_u[] values;
-    public int values_num;
     public double time;
     public double interval;
     [MarshalAs(UnmanagedType.LPStr)]
@@ -321,21 +343,9 @@ namespace CollectdAPI
     [MarshalAs(UnmanagedType.LPStr)]
     public string type_instance;
 
-    public value_list_s (ValueList vl)
+    /* Create a value_data_s structure from a ValueList object */
+    public value_data_s (ValueList vl)
     {
-      IList values = vl.GetValues ();
-
-      this.values_num = values.Count;
-      this.values = new value_u[this.values_num];
-      for (int i = 0; i < values.Count; i++)
-      {
-        IValue v = values[i] as IValue;
-
-        if (v is GaugeValue)
-          this.values[i].gauge = v.ToDouble ();
-        else
-          this.values[i].derive = v.ToLong ();
-      }
       this.time = vl.Time;
       this.interval = vl.Interval;
 
@@ -345,7 +355,23 @@ namespace CollectdAPI
       this.type = vl.Type;
       this.type_instance = vl.TypeInstance;
     }
-  } /* }}} struct value_list_s */
+  } /* }}} struct value_data_s */
+
+  internal class WriteMarshaler /* {{{ */
+  {
+    private CollectdWriteCallback _func;
+
+    public WriteMarshaler (CollectdWriteCallback func)
+    {
+      this._func = func;
+    }
+
+    public int invoke (value_data_s vd,
+        int values_len, value_u[] values, int[] values_types)
+    {
+      return (this._func (new ValueList (vd, values_len, values, values_types)));
+    }
+  } /* }}} class WriteMarshaler */
 
   /// <summary>
   /// This is the main class for interacting with collectd.
@@ -356,8 +382,21 @@ namespace CollectdAPI
   /// </remarks>
   public class Collectd /* {{{ */
   {
-    private static Hashtable _readFunctions = new Hashtable ();
     private static Hashtable _initFunctions = new Hashtable ();
+    private static Hashtable _readFunctions = new Hashtable ();
+    private static Hashtable _writeFunctions = new Hashtable ();
+
+    private delegate int MarshaledWriteCallback (value_data_s vd,
+        int values_len,
+        [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] value_u[] values,
+        [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] int[] values_types);
+
+    /* Const membes are static by default, so we're not allowed to specify that
+     * again. */
+    public const int DS_TYPE_COUNTER  = 0;
+    public const int DS_TYPE_GAUGE    = 1;
+    public const int DS_TYPE_DERIVE   = 2;
+    public const int DS_TYPE_ABSOLUTE = 3;
 
     [DllImport("__Internal", EntryPoint="plugin_log")]
     private extern static int _log (
@@ -374,8 +413,16 @@ namespace CollectdAPI
         [MarshalAs(UnmanagedType.LPStr)] string name,
         CollectdReadCallback func);
 
+    [DllImport("__Internal", EntryPoint="dotnet_register_write")]
+    private extern static int _registerWrite (
+        [MarshalAs(UnmanagedType.LPStr)] string name,
+        MarshaledWriteCallback func);
+
     [DllImport("__Internal", EntryPoint="dotnet_dispatch_values")]
-    private extern static int _dispatchValues (value_list_s vl);
+    private extern static int _dispatchValues (ref value_data_s vd,
+        int values_len,
+        /* [MarshalAs(UnmanagedType.LPArray)] */ value_u[] values
+        );
 
     /// <summary>Logs an error message.</summary>
     /// <remarks>Do not include a newline at the end.</remarks>
@@ -434,10 +481,37 @@ namespace CollectdAPI
       return (_registerRead (name, func));
     }
 
+    public static int RegisterWrite (string name, CollectdWriteCallback func)
+    {
+      WriteMarshaler marshaler = new WriteMarshaler (func);
+
+      /* Keep a copy of the object so it isn't garbage collected */
+      if (_writeFunctions.Contains (name))
+        return (-1);
+      _writeFunctions.Add (name, marshaler);
+
+      return (_registerWrite (name, new MarshaledWriteCallback (marshaler.invoke)));
+    }
+
     /// <summary>Dispatches a <code>ValueList</code> to the daemon.</summary>
     public static int DispatchValues (ValueList vl)
     {
-      return (_dispatchValues (new value_list_s (vl)));
+      IList        list       = vl.GetValues ();
+      value_data_s vd         = new value_data_s (vl);
+      int          values_len = list.Count;
+      value_u[]    values     = new value_u[values_len];
+
+      for (int i = 0; i < values_len; i++)
+      {
+        IValue v = list[i] as IValue;
+
+        if (v is GaugeValue)
+          values[i].gauge = v.ToDouble ();
+        else
+          values[i].derive = v.ToLong ();
+      }
+
+      return (_dispatchValues (ref vd, values_len, values));
     }
   } /* }}} class Collectd */
 }
index 374f93c..80431ea 100644 (file)
@@ -6,6 +6,7 @@ public class EmbedTest
        {
                Collectd.LogInfo ("EmbedTest plugin: Initializing the module.");
                Collectd.RegisterRead ("EmbedTest", new CollectdReadCallback (read));
+               // Collectd.RegisterWrite ("EmbedTest", new CollectdWriteCallback (write));
        }
 
        public int read ()
@@ -20,5 +21,11 @@ public class EmbedTest
                Collectd.DispatchValues (vl);
                return (0);
        }
+
+       public int write (ValueList vl)
+       {
+               Collectd.LogInfo ("EmbedTest plugin: write() called.");
+               return (0);
+       }
 }
 
index da5a81b..9f0204f 100644 (file)
 
 struct dotnet_value_list_s
 {
-  value_t *values;
-  int values_len;
   double time;
   double interval;
-  char *host;
-  char *plugin;
-  char *plugin_instance;
-  char *type;
-  char *type_instance;
+  const char *host;
+  const char *plugin;
+  const char *plugin_instance;
+  const char *type;
+  const char *type_instance;
 };
-typedef struct dotnet_value_list_s dotnet_value_list_t;
+typedef struct dotnet_value_list_s dotnet_value_data_t;
 
 #define CB_TYPE_INIT         2
 struct dotnet_callback_info_s;
@@ -60,6 +58,8 @@ struct dotnet_callback_info_s
 };
 
 typedef int (*dotnet_read_cb) (void);
+typedef int (*dotnet_write_cb) (dotnet_value_data_t *vd,
+    int values_len, value_t *values, int *values_types);
 
 static MonoDomain *_domain = NULL;
 static dotnet_callback_info_t *callback_list = NULL;
@@ -93,6 +93,33 @@ static int dotnet_read (user_data_t *ud) /* {{{ */
   return ((*cb) ());
 } /* }}} int dotnet_read */
 
+static int dotnet_write (const data_set_t *ds, const value_list_t *vl, /* {{{ */
+    user_data_t *ud)
+{
+  dotnet_write_cb cb = ud->data;
+  dotnet_value_data_t vd;
+  int values_types[vl->values_len];
+  int status;
+  int i;
+
+  DEBUG ("dotnet plugin: dotnet_write ();");
+
+  memset (&vd, 0, sizeof (vd));
+  vd.time = CDTIME_T_TO_DOUBLE (vl->time);
+  vd.interval = CDTIME_T_TO_DOUBLE (vl->interval);
+  vd.host = vl->host;
+  vd.plugin = vl->plugin;
+  vd.plugin_instance = vl->plugin_instance;
+  vd.type = vl->type;
+  vd.type_instance = vl->type_instance;
+
+  for (i = 0; i < ds->ds_num; i++)
+    values_types[i] = ds->ds[i].type;
+
+  status = (*cb) (&vd, vl->values_len, vl->values, values_types);
+  return (status);
+} /* }}} int dotnet_write */
+
 /*
  * Functions exposed to .Net
  */
@@ -141,28 +168,47 @@ int dotnet_register_read (const char *name, dotnet_read_cb cb) /* {{{ */
   return (0);
 } /* }}} int dotnet_register_read */
 
-int dotnet_dispatch_values (dotnet_value_list_t *dvl) /* {{{ */
+int dotnet_register_write (const char *name, dotnet_write_cb cb) /* {{{ */
+{
+  user_data_t ud;
+
+  DEBUG ("dotnet plugin: dotnet_register_write (\"%s\");", name);
+
+  memset (&ud, 0, sizeof (ud));
+  ud.data = cb;
+  ud.free_func = NULL;
+
+  plugin_register_write (name, dotnet_write, &ud);
+
+  return (0);
+} /* }}} int dotnet_register_write */
+
+int dotnet_dispatch_values (dotnet_value_data_t *vd, /* {{{ */
+    int values_len, value_t *values)
 {
   value_list_t vl = VALUE_LIST_INIT;
 
-  vl.values = dvl->values;
-  vl.values_len = dvl->values_len;
+  DEBUG ("dotnet_dispatch_values (vd = %p, values_len = %i, values = %p);",
+      (void *) vd, values_len, (void *) values);
 
-  if (dvl->time > 0.0)
-    vl.time = DOUBLE_TO_CDTIME_T (dvl->time);
+  vl.values_len = values_len;
+  vl.values = values;
+
+  if (vd->time > 0.0)
+    vl.time = DOUBLE_TO_CDTIME_T (vd->time);
   else
     vl.interval = 0;
 
-  if (dvl->interval > 0.0)
-    vl.interval = DOUBLE_TO_CDTIME_T (dvl->interval);
+  if (vd->interval > 0.0)
+    vl.interval = DOUBLE_TO_CDTIME_T (vd->interval);
   else
     vl.interval = interval_g;
 
-  sstrncpy (vl.host, dvl->host, sizeof (vl.host));
-  sstrncpy (vl.plugin, dvl->plugin, sizeof (vl.plugin));
-  sstrncpy (vl.plugin_instance, dvl->plugin_instance, sizeof (vl.plugin_instance));
-  sstrncpy (vl.type, dvl->type, sizeof (vl.type));
-  sstrncpy (vl.type_instance, dvl->type_instance, sizeof (vl.type_instance));
+  sstrncpy (vl.host, vd->host, sizeof (vl.host));
+  sstrncpy (vl.plugin, vd->plugin, sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, vd->plugin_instance, sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, vd->type, sizeof (vl.type));
+  sstrncpy (vl.type_instance, vd->type_instance, sizeof (vl.type_instance));
 
   return (plugin_dispatch_values (&vl));
 } /* }}} int dotnet_dispatch_values */
@@ -180,6 +226,12 @@ static int dotnet_load_class (const char *assembly_name, /* {{{ */
   MonoClass *class;
   MonoObject *obj;
 
+  DEBUG ("dotnet plugin: dotnet_load_class ("
+      "assembly_name = \"%s\", "
+      "name_space = \"%s\", "
+      "class_name = \"%s\");",
+      assembly_name, (name_space != NULL) ? name_space : "", class_name);
+
   domain = mono_domain_create ();
   if (domain == NULL)
   {
@@ -243,6 +295,7 @@ static int dotnet_load_class (const char *assembly_name, /* {{{ */
     return (-1);
   }
 
+  DEBUG ("dotnet plugin: mono_runtime_object_init ();");
   mono_runtime_object_init (obj);
 
   DEBUG ("dotnet plugin: Successfully created a \"%s\" object.", class_name);