From 4a62f5892aff5de5e39881afbfd793a908e16db8 Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Thu, 30 Dec 2010 08:15:27 +0100 Subject: [PATCH] dotnet plugin: Some work towards write callbacks. --- bindings/csharp/collectd.cs | 116 ++++++++++++++++++++++++++++++++++++-------- bindings/csharp/test.cs | 7 +++ src/dotnet.c | 93 +++++++++++++++++++++++++++-------- 3 files changed, 175 insertions(+), 41 deletions(-) diff --git a/bindings/csharp/collectd.cs b/bindings/csharp/collectd.cs index 061c16d3..c4937996 100644 --- a/bindings/csharp/collectd.cs +++ b/bindings/csharp/collectd.cs @@ -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 */ /// /// This is the main class for interacting with collectd. @@ -356,8 +382,21 @@ namespace CollectdAPI /// 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 + ); /// Logs an error message. /// Do not include a newline at the end. @@ -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))); + } + /// Dispatches a ValueList to the daemon. 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 */ } diff --git a/bindings/csharp/test.cs b/bindings/csharp/test.cs index 374f93c1..80431eac 100644 --- a/bindings/csharp/test.cs +++ b/bindings/csharp/test.cs @@ -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); + } } diff --git a/src/dotnet.c b/src/dotnet.c index da5a81bd..9f0204fa 100644 --- a/src/dotnet.c +++ b/src/dotnet.c @@ -36,17 +36,15 @@ 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); -- 2.11.0