From: ksjoberg Date: Thu, 5 Sep 2013 10:55:31 +0000 (+0200) Subject: Fix info memleak, cleanup, throw exceptions instead of return codes X-Git-Tag: v1.5.0-rc1~170^2^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F416%2Fhead;p=thirdparty%2Frrdtool-1.x.git Fix info memleak, cleanup, throw exceptions instead of return codes --- diff --git a/bindings/dotnet/RrdException.cs b/bindings/dotnet/RrdException.cs new file mode 100644 index 00000000..521c9c44 --- /dev/null +++ b/bindings/dotnet/RrdException.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace dnrrdlib +{ + public class RrdException : Exception + { + public RrdException() + : base(rrd.Get_Error()) + { + rrd.rrd_clear_error(); + } + } +} diff --git a/bindings/dotnet/dnrrdlib.csproj b/bindings/dotnet/dnrrdlib.csproj index f361c0b9..c08f623c 100644 --- a/bindings/dotnet/dnrrdlib.csproj +++ b/bindings/dotnet/dnrrdlib.csproj @@ -108,6 +108,7 @@ + diff --git a/bindings/dotnet/rrd_binding_test.cs b/bindings/dotnet/rrd_binding_test.cs index 09bab0b4..807bc551 100644 --- a/bindings/dotnet/rrd_binding_test.cs +++ b/bindings/dotnet/rrd_binding_test.cs @@ -16,6 +16,7 @@ using System; using System.Collections; using System.Runtime.InteropServices; using dnrrdlib; +using System.IO; namespace dnrrd_binding_test { @@ -53,51 +54,25 @@ namespace dnrrd_binding_test al.Add("RRA:AVERAGE:0.5:1:24"); al.Add("RRA:AVERAGE:0.5:6:10"); - int ret = rrd.Create(path + "test_a.rrd", 300, 920804400, (string[])al.ToArray(typeof(string))); - if (ret < 0) - Console.WriteLine("Error: " + rrd.Get_Error()); - else - Console.WriteLine("Test create: Successful!"); + rrd.Create(path + "test_a.rrd", 300, 920804400, (string[])al.ToArray(typeof(string))); + Console.WriteLine("Test create: Successful!"); } static void Test_Get_Info() { Console.WriteLine("Try getting info..."); - rrd_info_t? info = rrd.Info(path + "test_a.rrd"); - if (info == null) - { - Console.WriteLine("Error: " + rrd.Get_Error()); - return; - } - while (info != null) + var info = rrd.Info(path + "test_a.rrd"); + foreach (var kvp in info) { //info = (rrd_info_t)Marshal.PtrToStructure(info.next, typeof(rrd_info_t)); - Console.Write(((rrd_info_t)info).key + ": "); - switch (((rrd_info_t)info).type) + Console.Write(kvp.Key + ": "); + if (kvp.Value is string) { - case rrd_info_type_t.RD_I_STR: - Console.WriteLine("\"" + Marshal.PtrToStringAnsi(((rrd_info_t)info).value.u_str) + "\""); - break; - case rrd_info_type_t.RD_I_INT: - Console.WriteLine(((rrd_info_t)info).value.u_int); - break; - case rrd_info_type_t.RD_I_CNT: - Console.WriteLine(((rrd_info_t)info).value.u_cnt); - break; - case rrd_info_type_t.RD_I_VAL: - Console.WriteLine(((rrd_info_t)info).value.u_val); - break; - case rrd_info_type_t.RD_I_BLO: - Console.WriteLine(" ** BLOB ** "); - break; - default: - Console.WriteLine("**** Unknown type! ****"); - break; + Console.WriteLine("\"" + kvp.Value + "\""); } - - if (((rrd_info_t)info).next != IntPtr.Zero && (int)((rrd_info_t)info).next > 0) - info = (rrd_info_t)Marshal.PtrToStructure(((rrd_info_t)info).next, typeof(rrd_info_t)); else - info = null; + { + Console.WriteLine(kvp.Value); + } } Console.WriteLine("Test Info: Successful!"); //Console.WriteLine("Printing information..."); @@ -136,11 +111,8 @@ namespace dnrrd_binding_test ts += 300; } } - int ret = rrd.Update(path + "test_a.rrd", null, (string[])al.ToArray(typeof(string))); - if (ret < 0) - Console.WriteLine("Error: " + rrd.Get_Error()); - else - Console.WriteLine("Test update: Successful!"); + rrd.Update(path + "test_a.rrd", null, (string[])al.ToArray(typeof(string))); + Console.WriteLine("Test update: Successful!"); } static void Test_Fetch() { @@ -156,16 +128,16 @@ namespace dnrrd_binding_test al.Add("920809200"); IntPtr data = new IntPtr(); string[] rrds = new string[0]; - Int32 start = 0; - Int32 end = 0; + DateTime start = default(DateTime); + DateTime end = default(DateTime); UInt32 step = 0; UInt32 dscnt = 0; - int ret = rrd.Fetch((string[])al.ToArray(typeof(string)), ref start, ref end, + rrd.Fetch((string[])al.ToArray(typeof(string)), ref start, ref end, ref step, ref dscnt, ref rrds, ref data); if (end > start) { - for (Int32 ti = start + (Int32)step; ti <= end; ti += (Int32)step) + for (Int32 ti = rrd.DateTimeToUnixTimestamp(start); ti < rrd.DateTimeToUnixTimestamp(end); ti += (Int32)step) { Console.Write(ti + ": "); for (Int32 i = 0; i < (Int32)dscnt; i++) @@ -177,10 +149,7 @@ namespace dnrrd_binding_test } } - if (ret < 0) - Console.WriteLine("Error: " + rrd.Get_Error()); - else - Console.WriteLine("Test fetch: Successful!"); + Console.WriteLine("Test fetch: Successful!"); } static void Test_Graph() { @@ -194,11 +163,10 @@ namespace dnrrd_binding_test al.Add("920808000"); al.Add("DEF:myspeed=" + path.Replace(":", "\\:") + "test_a.rrd:speed:AVERAGE"); al.Add("LINE2:myspeed#00004D"); - int ret = rrd.Graph((string[])al.ToArray(typeof(string))); - if (ret < 0) - Console.WriteLine("Error: " + rrd.Get_Error()); - else - Console.WriteLine("Test graph: Successful!"); + + var ret = rrd.Graph((string[])al.ToArray(typeof(string))); + //TODO: Validate the returned data + Console.WriteLine("Test graph: Successful!"); } static void Test_Graph_Math() { @@ -215,11 +183,9 @@ namespace dnrrd_binding_test al.Add("DEF:myspeed=" + path.Replace(":", "\\:") + "test_a.rrd:speed:AVERAGE"); al.Add("CDEF:realspeed=myspeed,1000,*"); al.Add("LINE2:realspeed#00004D"); - int ret = rrd.Graph((string[])al.ToArray(typeof(string))); - if (ret < 0) - Console.WriteLine("Error: " + rrd.Get_Error()); - else - Console.WriteLine("Test graph: Successful!"); + var ret = rrd.Graph((string[])al.ToArray(typeof(string))); + //TODO: Validate the returned data + Console.WriteLine("Test graph: Successful!"); } static void Test_Graph_Math2() { @@ -240,11 +206,9 @@ namespace dnrrd_binding_test al.Add("HRULE:100#0000FF:\"Maximum allowed\""); al.Add("AREA:good#00FF00:\"Good speed\""); al.Add("AREA:fast#FF0000:\"Too fast\""); - int ret = rrd.Graph((string[])al.ToArray(typeof(string))); - if (ret < 0) - Console.WriteLine("Error: " + rrd.Get_Error()); - else - Console.WriteLine("Test graph: Successful!"); + var ret = rrd.Graph((string[])al.ToArray(typeof(string))); + //TODO: Validate the returned data + Console.WriteLine("Test graph: Successful!"); } static void Test_Graph_Math3() { @@ -268,11 +232,9 @@ namespace dnrrd_binding_test al.Add("AREA:good#00FF00:\"Good speed\""); al.Add("AREA:fast#550000:\"Too fast\""); al.Add("STACK:over#FF0000:\"Over speed\""); - int ret = rrd.Graph((string[])al.ToArray(typeof(string))); - if (ret < 0) - Console.WriteLine("Error: " + rrd.Get_Error()); - else - Console.WriteLine("Test graph: Successful!"); + var ret = rrd.Graph((string[])al.ToArray(typeof(string))); + //TODO: Validate the returned data + Console.WriteLine("Test graph: Successful!"); } static void Test_First_Last() { @@ -286,7 +248,7 @@ namespace dnrrd_binding_test if (err.Length > 1) Console.WriteLine("Error: " + err); - Int32 last_update = 0; + DateTime last_update = default(DateTime); UInt32 ds_count = 0; string[] ds_names = new string[0]; string[] last_ds = new string[0]; @@ -297,11 +259,8 @@ namespace dnrrd_binding_test static void Test_Dump() { Console.WriteLine("Dumping RRD..."); - int ret = rrd.Dump(path + "test_a.rrd", path + "test_a.xml"); - if (ret < 0) - Console.WriteLine("Error: " + rrd.Get_Error()); - else - Console.WriteLine("Test Dump: Successful!"); + rrd.Dump(path + "test_a.rrd", path + "test_a.xml"); + Console.WriteLine("Test Dump: Successful!"); } static void Test_Xport() { @@ -316,16 +275,16 @@ namespace dnrrd_binding_test al.Add("XPORT:myspeed:\"MySpeed\""); IntPtr data = new IntPtr(); string[] legends = new string[0]; - Int32 start = 0; - Int32 end = 0; + DateTime start = default(DateTime); + DateTime end = default(DateTime); UInt32 step = 0; UInt32 col_cnt = 0; - int ret = rrd.Xport((string[])al.ToArray(typeof(string)), ref start, ref end, + rrd.Xport((string[])al.ToArray(typeof(string)), ref start, ref end, ref step, ref col_cnt, ref legends, ref data); if (end > start) { - for (Int32 ti = start + (Int32)step; ti <= end; ti += (Int32)step) + for (Int32 ti = rrd.DateTimeToUnixTimestamp(start); ti <= rrd.DateTimeToUnixTimestamp(end); ti += (Int32)step) { Console.Write(ti + ": "); for (Int32 i = 0; i < (Int32)col_cnt; i++) @@ -336,23 +295,24 @@ namespace dnrrd_binding_test Console.Write(Environment.NewLine); } } - if (ret < 0) - Console.WriteLine("Error: " + rrd.Get_Error()); - else - Console.WriteLine("Test xport: Successful!"); + Console.WriteLine("Test xport: Successful!"); } static void Test_Restore() { + FileInfo rrdDestination = new FileInfo(path + "restored_a.rrd"); + if (rrdDestination.Exists) + { + rrdDestination.Delete(); + } + Console.WriteLine("Restoring RRD..."); ArrayList al = new ArrayList(); al.Add("restore"); al.Add(path + "test_a.xml"); - al.Add(path + "restored_a.rrd"); - int ret = rrd.Restore((string[])al.ToArray(typeof(string))); - if (ret < 0) - Console.WriteLine("Error: " + rrd.Get_Error()); - else - Console.WriteLine("Test restore: Successful!"); + al.Add(rrdDestination.FullName); + + rrd.Restore((string[])al.ToArray(typeof(string))); + Console.WriteLine("Test restore: Successful!"); } static void Test_Tune() { @@ -362,11 +322,8 @@ namespace dnrrd_binding_test al.Add(path + "restored_a.rrd"); al.Add("-h"); al.Add("speed:650"); - int ret = rrd.Tune((string[])al.ToArray(typeof(string))); - if (ret < 0) - Console.WriteLine("Error: " + rrd.Get_Error()); - else - Console.WriteLine("Test tune: Successful!"); + rrd.Tune((string[])al.ToArray(typeof(string))); + Console.WriteLine("Test tune: Successful!"); } } } diff --git a/bindings/dotnet/rrdlib.cs b/bindings/dotnet/rrdlib.cs index f488cc40..97010aee 100644 --- a/bindings/dotnet/rrdlib.cs +++ b/bindings/dotnet/rrdlib.cs @@ -12,6 +12,7 @@ * For useage examples, please see the rrd_binding_test project. ****************************************************************************/ using System; +using System.Linq; using System.Collections.Generic; using System.Runtime.InteropServices; @@ -92,14 +93,16 @@ namespace dnrrdlib public class rrd { // Set this path to the location of your "rrdlib.dll" file - const string dll = @"C:\Programming\RRDTool\SVN\win32\DebugDLL\rrdlib.dll"; + const string dll = @"librrd-4.dll"; // IMPORTS - Main methods [DllImport(dll)] static extern Int32 rrd_create(Int32 argc, string[] argv); - [DllImport(dll)] static extern Int32 rrd_create_r([MarshalAs(UnmanagedType.LPStr)] string filename, - UInt32 pdp_step, Int32 last_up, Int32 argc, [MarshalAs(UnmanagedType.LPArray)] string[] argv); + [DllImport(dll)] static extern Int32 rrd_create_r([MarshalAs(UnmanagedType.LPStr)] string filename, + UInt32 pdp_step, Int64 last_up, Int32 argc, [MarshalAs(UnmanagedType.LPArray)] string[] argv); [DllImport(dll)] static extern IntPtr rrd_info_r(string filename); [DllImport(dll)] static extern void rrd_info_print(IntPtr data); + [DllImport(dll)] static extern void rrd_info_free(IntPtr data); + [DllImport(dll)] static extern Int32 rrd_update(Int32 argc, string[] argv); [DllImport(dll)] static extern IntPtr rrd_update_v(Int32 argc, string[] argv); [DllImport(dll)] static extern Int32 rrd_update_r(string filename, string template, Int32 argc, @@ -107,9 +110,9 @@ namespace dnrrdlib /* Do not use this until someone adds the FILE structure */ [DllImport(dll)] static extern Int32 rrd_graph(Int32 argc, string[] argv, ref string[] prdata, ref Int32 xsize, ref Int32 ysize, /* TODO - FILE, */ ref double ymin, ref double ymax); - [DllImport(dll)] static extern Int32 rrd_graph_v(Int32 argc, string[] argv); - [DllImport(dll)] static extern Int32 rrd_fetch(Int32 argc, string[] argv, ref Int32 start, - ref Int32 end, ref UInt32 step, [Out] out UInt32 ds_cnt, [Out] out IntPtr ds_namv, [Out] out IntPtr data); + [DllImport(dll)] static extern IntPtr rrd_graph_v(Int32 argc, string[] argv); + [DllImport(dll)] static extern Int32 rrd_fetch(Int32 argc, string[] argv, ref Int64 start, + ref Int64 end, ref UInt32 step, [Out] out UInt32 ds_cnt, [Out] out IntPtr ds_namv, [Out] out IntPtr data); [DllImport(dll)] static extern Int32 rrd_first(Int32 argc, string[] argv); [DllImport(dll)] static extern Int32 rrd_first_r(string filename, Int32 rraindex); [DllImport(dll)] static extern Int32 rrd_last(Int32 argc, string[] argv); @@ -120,7 +123,7 @@ namespace dnrrdlib [DllImport(dll)] static extern Int32 rrd_dump(Int32 argc, string[] argv); [DllImport(dll)] static extern Int32 rrd_dump_r(string filename, string outname); [DllImport(dll)] static extern Int32 rrd_xport(Int32 argc, string[] argv, Int32 unused, - ref Int32 start, ref Int32 end, ref UInt32 step, ref UInt32 col_cnt, + ref Int64 start, ref Int64 end, ref UInt32 step, ref UInt32 col_cnt, [Out] out IntPtr leggend_v, [Out] out IntPtr data); [DllImport(dll)] static extern Int32 rrd_restore(Int32 argc, string[] argv); [DllImport(dll)] static extern Int32 rrd_resize(Int32 argc, string[] argv); @@ -130,9 +133,20 @@ namespace dnrrdlib [DllImport(dll)] static extern string rrd_strversion(); [DllImport(dll)] static extern Int32 rrd_random(); [DllImport(dll)] static extern IntPtr rrd_get_error(); + [DllImport(dll)] internal static extern void rrd_clear_error(); // MAIN FUNCTIONS + public static DateTime UnixTimestampToDateTime(Int32 unixTimeStamp) + { + return new DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds(unixTimeStamp).ToLocalTime(); + } + + public static Int32 DateTimeToUnixTimestamp(DateTime input) + { + return (Int32)input.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds; + } + /// /// The create function of RRDtool lets you set up new Round Robin Database (RRD) files. /// The file is created at its final, full size and filled with *UNKNOWN* data. @@ -141,7 +155,7 @@ namespace dnrrdlib /// 0 if successful, -1 if an error occurred public static int Create(string[] argv) { - return rrd_create(argv.GetUpperBound(0) + 1, argv); + return rrd_create(argv.Length, argv); } /// @@ -152,10 +166,48 @@ namespace dnrrdlib /// Specifies the base interval in seconds with which data will be fed into the RRD /// Timestamp of the last update /// String array of command line arguments - /// 0 if successful, -1 if an error occurred - public static int Create(string filename, UInt32 pdp_step, Int32 last_up, string[] argv) + public static void Create(string filename, UInt32 pdp_step, Int32 last_up, string[] argv) { - return rrd_create_r(filename, pdp_step, last_up, argv.GetUpperBound(0)+1, argv); + if (rrd_create_r(filename, pdp_step, last_up, argv.Length, argv) < 0) + { + throw new RrdException(); + } + } + + private static Dictionary ConvertInfoToDict(IntPtr ptr) + { + var dict = new Dictionary(); + + rrd_info_t? info = (rrd_info_t)Marshal.PtrToStructure(ptr, typeof(rrd_info_t)); + + while (info.HasValue) + { + switch (info.Value.type) + { + case rrd_info_type_t.RD_I_STR: + dict.Add(info.Value.key, System.Runtime.InteropServices.Marshal.PtrToStringAnsi(info.Value.value.u_str)); + break; + case rrd_info_type_t.RD_I_INT: + dict.Add(info.Value.key, info.Value.value.u_int); + break; + case rrd_info_type_t.RD_I_CNT: + dict.Add(info.Value.key, info.Value.value.u_cnt); + break; + case rrd_info_type_t.RD_I_VAL: + dict.Add(info.Value.key, info.Value.value.u_val); + break; + case rrd_info_type_t.RD_I_BLO: + //TODO: Properly extract the byte array + dict.Add(info.Value.key, "[BLOB]"); + break; + } + + if (info.Value.next != IntPtr.Zero) + info = (rrd_info_t)System.Runtime.InteropServices.Marshal.PtrToStructure(info.Value.next, typeof(rrd_info_t)); + else + info = null; + } + return dict; } /// @@ -163,14 +215,17 @@ namespace dnrrdlib /// /// Full path to the rrd file /// An rrd_info_t object - public static rrd_info_t Info(string filename) + public static Dictionary Info(string filename) { - if (filename.Length < 1) + if (string.IsNullOrEmpty(filename)) throw new Exception("Empty filename"); IntPtr ptr = rrd_info_r(filename); - if (ptr == IntPtr.Zero || (int)ptr < 1) - throw new Exception("Unable to extract information from rrd"); - return (rrd_info_t)Marshal.PtrToStructure(ptr, typeof(rrd_info_t)); + if (ptr == IntPtr.Zero || ptr.ToInt64() == -1) + throw new RrdException(); + + var ret = ConvertInfoToDict(ptr); + rrd_info_free(ptr); + return ret; } /// @@ -179,9 +234,12 @@ namespace dnrrdlib /// /// String array of command line arguments /// 0 if successful, -1 if an error occurred - public static Int32 Update(string[] argv) + public static void Update(params string[] argv) { - return rrd_update(argv.GetUpperBound(0) + 1, argv); + if (rrd_update(argv.Length, argv) < 0) + { + throw new RrdException(); + } } /// @@ -190,9 +248,9 @@ namespace dnrrdlib /// /// String array of command line arguments /// An rrd_info_t pointer with information about the update - public static IntPtr Update2(string[] argv) + public static IntPtr Update2(params string[] argv) { - return rrd_update_v(argv.GetUpperBound(0) + 1, argv); + return rrd_update_v(argv.Length, argv); } /// @@ -202,10 +260,12 @@ namespace dnrrdlib /// Full path to the rrd to update /// List of data sources to update and in which order /// String array of command line arguments - /// 0 if successful, -1 if an error occurred - public static Int32 Update(string filename, string template, string[] argv) + public static void Update(string filename, string template, params string[] argv) { - return rrd_update_r(filename, template, argv.GetUpperBound(0)+1, argv); + if (rrd_update_r(filename, template, argv.Length, argv) < 0) + { + throw new RrdException(); + } } /// @@ -214,9 +274,16 @@ namespace dnrrdlib /// /// String array of command line arguments /// 0 if successful, -1 if an error occurred - public static Int32 Graph(string[] argv) + public static Dictionary Graph(params string[] argv) { - return rrd_graph_v(argv.GetUpperBound(0) + 1, argv); + IntPtr ptr = rrd_graph_v(argv.Length, argv); + + if (ptr == IntPtr.Zero || ptr.ToInt64() == -1) + throw new RrdException(); + + var ret = ConvertInfoToDict(ptr); + rrd_info_free(ptr); + return ret; } /// @@ -231,15 +298,19 @@ namespace dnrrdlib /// Number of data sources found /// Names of data sources found /// Values found (in double type) - /// 0 if successful, -1 if an error occurred - public static Int32 Fetch(string[] argv, ref Int32 start, ref Int32 end, ref UInt32 step, + public static void Fetch(string[] argv, ref DateTime start, ref DateTime end, ref UInt32 step, ref UInt32 ds_cnt, ref string[] ds_namv, ref IntPtr data) { + Int64 starti64 = 0, endi64 = 0; IntPtr ptr = new IntPtr(); - Int32 rv = rrd_fetch(argv.GetUpperBound(0) + 1, argv, ref start, ref end, ref step, out ds_cnt, - out ptr, out data); + if (rrd_fetch(argv.Length, argv, ref starti64, ref endi64, ref step, out ds_cnt, + out ptr, out data) < 0) + { + throw new RrdException(); + } ds_namv = GetStringArray(ptr, ds_cnt); - return rv; + start = UnixTimestampToDateTime((int)starti64); + end = UnixTimestampToDateTime((int)endi64); } /// @@ -250,7 +321,12 @@ namespace dnrrdlib /// Unix timestamp if successful, -1 if an error occurred public static Int32 First(string filename, int rraindex) { - return rrd_first_r(filename, rraindex); + Int32 rv = rrd_first_r(filename, rraindex); + if (rv < 0) + { + throw new RrdException(); + } + return rv; } /// @@ -258,9 +334,14 @@ namespace dnrrdlib /// /// String array of command line arguments /// Unix timestamp if successful, -1 if an error occurred - public static Int32 First(string[] argv) + public static Int32 First(params string[] argv) { - return rrd_first(argv.GetUpperBound(0) + 1, argv); + Int32 rv = rrd_first(argv.Length, argv); + if (rv < 0) + { + throw new RrdException(); + } + return rv; } /// @@ -270,9 +351,14 @@ namespace dnrrdlib /// Full path to the rrd file /// 0 based index of the rra to get a value for /// Unix timestamp if successful, -1 if an error occurred - public static Int32 Last(string filename, int rraindex) + public static DateTime Last(string filename, int rraindex) { - return rrd_last_r(filename, rraindex); + Int32 rv = rrd_last_r(filename, rraindex); + if (rv < 0) + { + throw new RrdException(); + } + return UnixTimestampToDateTime(rv); } /// @@ -280,9 +366,14 @@ namespace dnrrdlib /// /// String array of command line arguments /// Unix timestamp if successful, -1 if an error occurred - public static Int32 Last(string[] argv) + public static DateTime Last(params string[] argv) { - return rrd_last(argv.GetUpperBound(0) + 1, argv); + Int32 rv = rrd_last(argv.Length, argv); + if (rv < 0) + { + throw new RrdException(); + } + return UnixTimestampToDateTime(rv); } /// @@ -293,16 +384,20 @@ namespace dnrrdlib /// Number of data sources found /// Names of the data sources found /// Name of the last data source found - /// 0 if successful, -1 if an error occurred - public static Int32 Last_Update(string filename, ref Int32 ret_last_update, ref UInt32 ret_ds_count, + public static void Last_Update(string filename, ref DateTime ret_last_update, ref UInt32 ret_ds_count, ref string[] ret_ds_names, ref string[] ret_last_ds) { IntPtr ds_names = new IntPtr(); IntPtr last_ds = new IntPtr(); - Int32 rt = rrd_lastupdate_r(filename, ref ret_last_update, ref ret_ds_count, out ds_names,out last_ds); + Int32 last_update = 0; + Int32 rt = rrd_lastupdate_r(filename, ref last_update, ref ret_ds_count, out ds_names, out last_ds); + if (rt < 0) + { + throw new RrdException(); + } + ret_last_update = UnixTimestampToDateTime(last_update); ret_ds_names = GetStringArray(ds_names, ret_ds_count); ret_last_ds = GetStringArray(last_ds, 1); - return rt; } /// @@ -311,9 +406,12 @@ namespace dnrrdlib /// Full path to the rrd file /// Full path to write the XML output /// 0 if successful, -1 if an error occurred - public static Int32 Dump(string filename, string outname) + public static void Dump(string filename, string outname) { - return rrd_dump_r(filename, outname); + if (rrd_dump_r(filename, outname) < 0) + { + throw new RrdException(); + } } /// @@ -321,9 +419,12 @@ namespace dnrrdlib /// /// String array of command line arguments /// 0 if successful, -1 if an error occurred - public static Int32 Dump(string[] argv) + public static void Dump(params string[] argv) { - return rrd_dump(argv.GetUpperBound(0) + 1, argv); + if (rrd_dump(argv.Length, argv) < 0) + { + throw new RrdException(); + } } /// @@ -337,15 +438,20 @@ namespace dnrrdlib /// Number of data sources found in the rrd /// Add a legend /// Values from the rrd as double type - /// 0 if successful, -1 if an error occurred - public static Int32 Xport(string[] argv, ref Int32 start, ref Int32 end, ref UInt32 step, + public static void Xport(string[] argv, ref DateTime start, ref DateTime end, ref UInt32 step, ref UInt32 col_cnt, ref string[] legend_v, ref IntPtr data) { + Int64 starti64 = 0, endi64 = 0; IntPtr legend = new IntPtr(); - Int32 rt = rrd_xport(argv.GetUpperBound(0) + 1, argv, 0, ref start, ref end, ref step, ref col_cnt, + Int32 rt = rrd_xport(argv.Length, argv, 0, ref starti64, ref endi64, ref step, ref col_cnt, out legend, out data); + if (rt < 0) + { + throw new RrdException(); + } legend_v = GetStringArray(legend, col_cnt); - return rt; + start = UnixTimestampToDateTime((int)starti64); + end = UnixTimestampToDateTime((int)endi64); } /// @@ -353,9 +459,12 @@ namespace dnrrdlib /// /// String array of command line arguments /// 0 if successful, -1 if an error occurred - public static Int32 Restore(string[] argv) + public static void Restore(params string[] argv) { - return rrd_restore(argv.GetUpperBound(0) + 1, argv); + if (rrd_restore(argv.Length, argv) < 0) + { + throw new RrdException(); + } } /// @@ -364,20 +473,24 @@ namespace dnrrdlib /// NOTE: This may crash in version 1.4.3 /// /// String array of command line arguments - /// 0 if successful, -1 if an error occurred - public static Int32 Resize(string[] argv) + public static void Resize(params string[] argv) { - return rrd_resize(argv.GetUpperBound(0) + 1, argv); + if (rrd_resize(argv.Length, argv) < 0) + { + throw new RrdException(); + } } /// /// Modify the characteristics of an rrd /// /// String array of command line arguments - /// 0 if successful, -1 if an error occurred - public static Int32 Tune(string[] argv) + public static void Tune(params string[] argv) { - return rrd_tune(argv.GetUpperBound(0) + 1, argv); + if (rrd_tune(argv.Length, argv) < 0) + { + throw new RrdException(); + } } // UTILITIES @@ -415,11 +528,18 @@ namespace dnrrdlib /// Formats and prints information in the object to the standard output /// /// rrd_info_t object with data to print - public static void Info_Print(rrd_info_t info) + public static void Info_Print(string filename) { - IntPtr newptr = Marshal.AllocHGlobal(Marshal.SizeOf(info)); - Marshal.StructureToPtr(info, newptr, true); - rrd_info_print(newptr); + if (string.IsNullOrEmpty(filename)) + throw new Exception("Empty filename"); + IntPtr ptr = rrd_info_r(filename); + if (ptr == IntPtr.Zero || ptr.ToInt64() == -1) + throw new RrdException(); + + var data = (rrd_info_t)Marshal.PtrToStructure(ptr, typeof(rrd_info_t)); + + rrd_info_print(ptr); + rrd_info_free(ptr); } ///