]> git.ipfire.org Git - thirdparty/rrdtool-1.x.git/commitdiff
Fix info memleak, cleanup, throw exceptions instead of return codes 416/head
authorksjoberg <ksjoberg-github@q1.se>
Thu, 5 Sep 2013 10:55:31 +0000 (12:55 +0200)
committerksjoberg <ksjoberg-github@q1.se>
Thu, 5 Sep 2013 10:55:31 +0000 (12:55 +0200)
bindings/dotnet/RrdException.cs [new file with mode: 0644]
bindings/dotnet/dnrrdlib.csproj
bindings/dotnet/rrd_binding_test.cs
bindings/dotnet/rrdlib.cs

diff --git a/bindings/dotnet/RrdException.cs b/bindings/dotnet/RrdException.cs
new file mode 100644 (file)
index 0000000..521c9c4
--- /dev/null
@@ -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();
+        }
+    }
+}
index f361c0b99610bda7b5fc7b791cafbba2a4afa27a..c08f623c6b7907eefaada8cde98dd45f26bb3d45 100644 (file)
     <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="RrdException.cs" />
     <Compile Include="rrdlib.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>
index 09bab0b47cec7fd7d8253557c18fcb36f6d5fb10..807bc55192949d6f0883663852ed03d401408759 100644 (file)
@@ -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!");
         }
     }
 }
index f488cc40a98f706e00a173bf4544da21b49fc4e8..97010aee61afd56ddc3df9ef414a8265589f7886 100644 (file)
@@ -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;
+        }
+
         /// <summary>
         /// 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
         /// <returns>0 if successful, -1 if an error occurred</returns>
         public static int Create(string[] argv)
         {
-            return rrd_create(argv.GetUpperBound(0) + 1, argv);
+            return rrd_create(argv.Length, argv);
         }
 
         /// <summary>
@@ -152,10 +166,48 @@ namespace dnrrdlib
         /// <param name="pdp_step">Specifies the base interval in seconds with which data will be fed into the RRD</param>
         /// <param name="last_up">Timestamp of the last update</param>
         /// <param name="argv">String array of command line arguments</param>
-        /// <returns>0 if successful, -1 if an error occurred</returns>
-        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<string, object> ConvertInfoToDict(IntPtr ptr)
+        {
+            var dict = new Dictionary<string, object>();
+
+            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;
         }
 
         /// <summary>
@@ -163,14 +215,17 @@ namespace dnrrdlib
         /// </summary>
         /// <param name="filename">Full path to the rrd file</param>
         /// <returns>An rrd_info_t object</returns>
-        public static rrd_info_t Info(string filename)
+        public static Dictionary<string, object> 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;
         }
 
         /// <summary>
@@ -179,9 +234,12 @@ namespace dnrrdlib
         /// </summary>
         /// <param name="argv">String array of command line arguments</param>
         /// <returns>0 if successful, -1 if an error occurred</returns>
-        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();
+            }
         }
 
         /// <summary>
@@ -190,9 +248,9 @@ namespace dnrrdlib
         /// </summary>
         /// <param name="argv">String array of command line arguments</param>
         /// <returns>An rrd_info_t pointer with information about the update</returns>
-        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);
         }
 
         /// <summary>
@@ -202,10 +260,12 @@ namespace dnrrdlib
         /// <param name="filename">Full path to the rrd to update</param>
         /// <param name="template">List of data sources to update and in which order</param>
         /// <param name="argv">String array of command line arguments</param>
-        /// <returns>0 if successful, -1 if an error occurred</returns>
-        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();
+            }
         }
 
         /// <summary>
@@ -214,9 +274,16 @@ namespace dnrrdlib
         /// </summary>
         /// <param name="argv">String array of command line arguments</param>
         /// <returns>0 if successful, -1 if an error occurred</returns>
-        public static Int32 Graph(string[] argv)
+        public static Dictionary<string, object> 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;
         }
 
         /// <summary>
@@ -231,15 +298,19 @@ namespace dnrrdlib
         /// <param name="ds_cnt">Number of data sources found</param>
         /// <param name="ds_namv">Names of data sources found</param>
         /// <param name="data">Values found (in double type)</param>
-        /// <returns>0 if successful, -1 if an error occurred</returns>
-        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);
         }
 
         /// <summary>
@@ -250,7 +321,12 @@ namespace dnrrdlib
         /// <returns>Unix timestamp if successful, -1 if an error occurred</returns>
         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;
         }
 
         /// <summary>
@@ -258,9 +334,14 @@ namespace dnrrdlib
         /// </summary>
         /// <param name="argv">String array of command line arguments</param>
         /// <returns>Unix timestamp if successful, -1 if an error occurred</returns>
-        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;
         }
 
         /// <summary>
@@ -270,9 +351,14 @@ namespace dnrrdlib
         /// <param name="filename">Full path to the rrd file</param>
         /// <param name="rraindex">0 based index of the rra to get a value for</param>
         /// <returns>Unix timestamp if successful, -1 if an error occurred</returns>
-        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);
         }
 
         /// <summary>
@@ -280,9 +366,14 @@ namespace dnrrdlib
         /// </summary>
         /// <param name="argv">String array of command line arguments</param>
         /// <returns>Unix timestamp if successful, -1 if an error occurred</returns>
-        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);
         }
 
         /// <summary>
@@ -293,16 +384,20 @@ namespace dnrrdlib
         /// <param name="ret_ds_count">Number of data sources found</param>
         /// <param name="ret_ds_names">Names of the data sources found</param>
         /// <param name="ret_last_ds">Name of the last data source found</param>
-        /// <returns>0 if successful, -1 if an error occurred</returns>
-        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;
         }
 
         /// <summary>
@@ -311,9 +406,12 @@ namespace dnrrdlib
         /// <param name="filename">Full path to the rrd file</param>
         /// <param name="outname">Full path to write the XML output</param>
         /// <returns>0 if successful, -1 if an error occurred</returns>
-        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();
+            }
         }
 
         /// <summary>
@@ -321,9 +419,12 @@ namespace dnrrdlib
         /// </summary>
         /// <param name="argv">String array of command line arguments</param>
         /// <returns>0 if successful, -1 if an error occurred</returns>
-        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();
+            }
         }
 
         /// <summary>
@@ -337,15 +438,20 @@ namespace dnrrdlib
         /// <param name="col_cnt">Number of data sources found in the rrd</param>
         /// <param name="leggend_v">Add a legend</param>
         /// <param name="data">Values from the rrd as double type</param>
-        /// <returns>0 if successful, -1 if an error occurred</returns>
-        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);
         }
 
         /// <summary>
@@ -353,9 +459,12 @@ namespace dnrrdlib
         /// </summary>
         /// <param name="argv">String array of command line arguments</param>
         /// <returns>0 if successful, -1 if an error occurred</returns>
-        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();
+            }
         }
 
         /// <summary>
@@ -364,20 +473,24 @@ namespace dnrrdlib
         /// NOTE: This may crash in version 1.4.3
         /// </summary>
         /// <param name="argv">String array of command line arguments</param>
-        /// <returns>0 if successful, -1 if an error occurred</returns>
-        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();
+            }
         }
 
         /// <summary>
         /// Modify the characteristics of an rrd
         /// </summary>
         /// <param name="argv">String array of command line arguments</param>
-        /// <returns>0 if successful, -1 if an error occurred</returns>
-        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
         /// </summary>
         /// <param name="info">rrd_info_t object with data to print</param>
-        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);
         }
 
         /// <summary>