1 /*****************************************************************************
2 * RRDLIB .NET Binding
3 *****************************************************************************
4 * Created 2010/06/29 by Chris Larsen
5 *
6 * This .NET interface allows the use of Tobias Oetiker's awesome RRDtool
7 * functions in .NET projects using the PInvoke method to load the rrdlib.dll
8 * To use, please make sure that you place the rrdlib.dll in the same
9 * directory as this dll, or change the "const string dll" to point to the
10 * proper location. For documentation, please see the RRDtool website at:
11 * http://oss.oetiker.ch/rrdtool/
12 * For useage examples, please see the rrd_binding_test project.
13 ****************************************************************************/
14 using System;
15 using System.Collections.Generic;
16 using System.Runtime.InteropServices;
18 /// <summary>
19 /// Contains data structures and methods for working with round robin databases.
20 /// </summary>
21 namespace dnrrdlib
22 {
23 /// <summary>
24 /// Information about a particular RRD parameter. The key is the name of the parameter,
25 /// type determines what kind of value we have, value is the value, and next is a
26 /// pointer to another info object.
27 /// </summary>
28 [StructLayout(LayoutKind.Explicit, Pack = 1)]
29 public struct rrd_info_t
30 {
31 [FieldOffset(0), MarshalAs(UnmanagedType.LPStr)]
32 public string key;
33 [FieldOffset(4)] // for 64 bit, set this to 8 and increment everyone else by 4
34 public rrd_info_type_t type;
35 [FieldOffset(8)]
36 public rrd_infoval_t value;
37 [FieldOffset(16)]
38 public IntPtr next;
39 }
41 /// <summary>
42 /// This is a chunk of data returned from an RRD object
43 /// </summary>
44 [StructLayout(LayoutKind.Sequential)]
45 public struct rrd_blob_t
46 {
47 public UInt32 size; /* size of the blob */
48 public IntPtr ptr; /* pointer */
49 };
51 /// <summary>
52 /// This contains the actual data values for an rrd_info_t structure.
53 /// NOTE: Only one of these will be valid per instance. Use the containing info_t's
54 /// type field to deteremine which of these to read.
55 /// NOTE: If the type is RD_I_STR, you have to marshal the string value yourself
56 /// </summary>
57 [StructLayout(LayoutKind.Explicit)]
58 public struct rrd_infoval_t
59 {
60 [FieldOffset(0)]
61 public UInt32 u_cnt;
62 [FieldOffset(0)]
63 public double u_val;
64 [FieldOffset(0)]
65 public IntPtr u_str;
66 [FieldOffset(0)]
67 public Int32 u_int;
68 [FieldOffset(0)]
69 public rrd_blob_t u_blo;
70 };
72 /// <summary>
73 /// Different rrd_info_t value types
74 /// </summary>
75 public enum rrd_info_type_t
76 {
77 RD_I_VAL = 0,
78 RD_I_CNT,
79 RD_I_STR,
80 RD_I_INT,
81 RD_I_BLO
82 };
84 /// <summary>
85 /// Direct bindings to the RRD Library for .NET applications. Uses the PInvoke method
86 /// of accessing the rrdlib.dll file.
87 /// </summary>
88 public class rrd
89 {
90 // Set this path to the location of your "rrdlib.dll" file
91 const string dll = @"C:\Programming\RRDTool\SVN\win32\DebugDLL\rrdlib.dll";
93 // IMPORTS - Main methods
94 [DllImport(dll)] static extern Int32 rrd_create(Int32 argc, string[] argv);
95 [DllImport(dll)] static extern Int32 rrd_create_r([MarshalAs(UnmanagedType.LPStr)] string filename,
96 UInt32 pdp_step, Int32 last_up, Int32 argc, [MarshalAs(UnmanagedType.LPArray)] string[] argv);
97 [DllImport(dll)] static extern IntPtr rrd_info_r(string filename);
98 [DllImport(dll)] static extern void rrd_info_print(IntPtr data);
99 [DllImport(dll)] static extern Int32 rrd_update(Int32 argc, string[] argv);
100 [DllImport(dll)] static extern IntPtr rrd_update_v(Int32 argc, string[] argv);
101 [DllImport(dll)] static extern Int32 rrd_update_r(string filename, string template, Int32 argc,
102 string[] argv);
103 /* Do not use this until someone adds the FILE structure */
104 [DllImport(dll)] static extern Int32 rrd_graph(Int32 argc, string[] argv, ref string[] prdata,
105 ref Int32 xsize, ref Int32 ysize, /* TODO - FILE, */ ref double ymin, ref double ymax);
106 [DllImport(dll)] static extern Int32 rrd_graph_v(Int32 argc, string[] argv);
107 [DllImport(dll)] static extern Int32 rrd_fetch(Int32 argc, string[] argv, ref Int32 start,
108 ref Int32 end, ref UInt32 step, [Out] out UInt32 ds_cnt, [Out] out IntPtr ds_namv, [Out] out IntPtr data);
109 [DllImport(dll)] static extern Int32 rrd_first(Int32 argc, string[] argv);
110 [DllImport(dll)] static extern Int32 rrd_first_r(string filename, Int32 rraindex);
111 [DllImport(dll)] static extern Int32 rrd_last(Int32 argc, string[] argv);
112 [DllImport(dll)] static extern Int32 rrd_last_r(string filename, Int32 rraindex);
113 [DllImport(dll)] static extern Int32 rrd_lastupdate(Int32 argc, string[] argv);
114 [DllImport(dll)] static extern Int32 rrd_lastupdate_r(string filename, ref Int32 ret_last_update,
115 ref UInt32 ret_ds_count, [Out] out IntPtr ret_ds_names, [Out] out IntPtr ret_last_ds);
116 [DllImport(dll)] static extern Int32 rrd_dump(Int32 argc, string[] argv);
117 [DllImport(dll)] static extern Int32 rrd_dump_r(string filename, string outname);
118 [DllImport(dll)] static extern Int32 rrd_xport(Int32 argc, string[] argv, Int32 unused,
119 ref Int32 start, ref Int32 end, ref UInt32 step, ref UInt32 col_cnt,
120 [Out] out IntPtr leggend_v, [Out] out IntPtr data);
121 [DllImport(dll)] static extern Int32 rrd_restore(Int32 argc, string[] argv);
122 [DllImport(dll)] static extern Int32 rrd_resize(Int32 argc, string[] argv);
123 [DllImport(dll)] static extern Int32 rrd_tune(Int32 argc, string[] argv);
125 // IMPORTS - Utility methods
126 [DllImport(dll)] static extern string rrd_strversion();
127 [DllImport(dll)] static extern Int32 rrd_random();
128 [DllImport(dll)] static extern IntPtr rrd_get_error();
130 // MAIN FUNCTIONS
132 /// <summary>
133 /// The create function of RRDtool lets you set up new Round Robin Database (RRD) files.
134 /// The file is created at its final, full size and filled with *UNKNOWN* data.
135 /// </summary>
136 /// <param name="argv">String array of command line arguments</param>
137 /// <returns>0 if successful, -1 if an error occurred</returns>
138 public static int Create(string[] argv)
139 {
140 return rrd_create(argv.GetUpperBound(0) + 1, argv);
141 }
143 /// <summary>
144 /// The create function of RRDtool lets you set up new Round Robin Database (RRD) files.
145 /// The file is created at its final, full size and filled with *UNKNOWN* data.
146 /// </summary>
147 /// <param name="filename">A full path to the location where you want the rrd to reside</param>
148 /// <param name="pdp_step">Specifies the base interval in seconds with which data will be fed into the RRD</param>
149 /// <param name="last_up">Timestamp of the last update</param>
150 /// <param name="argv">String array of command line arguments</param>
151 /// <returns>0 if successful, -1 if an error occurred</returns>
152 public static int Create(string filename, UInt32 pdp_step, Int32 last_up, string[] argv)
153 {
154 return rrd_create_r(filename, pdp_step, last_up, argv.GetUpperBound(0)+1, argv);
155 }
157 /// <summary>
158 /// Returns a linked list of rrd_info_t objects that describe the rrd file.
159 /// </summary>
160 /// <param name="filename">Full path to the rrd file</param>
161 /// <returns>An rrd_info_t object</returns>
162 public static rrd_info_t Info(string filename)
163 {
164 if (filename.Length < 1)
165 throw new Exception("Empty filename");
166 IntPtr ptr = rrd_info_r(filename);
167 if (ptr == IntPtr.Zero || (int)ptr < 1)
168 throw new Exception("Unable to extract information from rrd");
169 return (rrd_info_t)Marshal.PtrToStructure(ptr, typeof(rrd_info_t));
170 }
172 /// <summary>
173 /// The update function feeds new data values into an RRD. The data is time aligned (interpolated)
174 /// according to the properties of the RRD to which the data is written.
175 /// </summary>
176 /// <param name="argv">String array of command line arguments</param>
177 /// <returns>0 if successful, -1 if an error occurred</returns>
178 public static Int32 Update(string[] argv)
179 {
180 return rrd_update(argv.GetUpperBound(0) + 1, argv);
181 }
183 /// <summary>
184 /// The update function feeds new data values into an RRD. The data is time aligned (interpolated)
185 /// according to the properties of the RRD to which the data is written.
186 /// </summary>
187 /// <param name="argv">String array of command line arguments</param>
188 /// <returns>An rrd_info_t pointer with information about the update</returns>
189 public static IntPtr Update2(string[] argv)
190 {
191 return rrd_update_v(argv.GetUpperBound(0) + 1, argv);
192 }
194 /// <summary>
195 /// The update function feeds new data values into an RRD. The data is time aligned (interpolated)
196 /// according to the properties of the RRD to which the data is written.
197 /// </summary>
198 /// <param name="filename">Full path to the rrd to update</param>
199 /// <param name="template">List of data sources to update and in which order</param>
200 /// <param name="argv">String array of command line arguments</param>
201 /// <returns>0 if successful, -1 if an error occurred</returns>
202 public static Int32 Update(string filename, string template, string[] argv)
203 {
204 return rrd_update_r(filename, template, argv.GetUpperBound(0)+1, argv);
205 }
207 /// <summary>
208 /// Generate a graph from an RRD file. Specify all the graph options in the string array as you
209 /// normally would with the command line version.
210 /// </summary>
211 /// <param name="argv">String array of command line arguments</param>
212 /// <returns>0 if successful, -1 if an error occurred</returns>
213 public static Int32 Graph(string[] argv)
214 {
215 return rrd_graph_v(argv.GetUpperBound(0) + 1, argv);
216 }
218 /// <summary>
219 /// Returns an array of values for the period specified from a given rrd.
220 /// Specify your parameters in the argv array and check the referenced parameters for
221 /// values returned from the rrd
222 /// </summary>
223 /// <param name="argv">String array of command line arguments (must include the filename)</param>
224 /// <param name="start">Starting timestamp found in the rrd</param>
225 /// <param name="end">Ending timestamp found in the rrd</param>
226 /// <param name="step">The rrd's step value</param>
227 /// <param name="ds_cnt">Number of data sources found</param>
228 /// <param name="ds_namv">Names of data sources found</param>
229 /// <param name="data">Values found (in double type)</param>
230 /// <returns>0 if successful, -1 if an error occurred</returns>
231 public static Int32 Fetch(string[] argv, ref Int32 start, ref Int32 end, ref UInt32 step,
232 ref UInt32 ds_cnt, ref string[] ds_namv, ref IntPtr data)
233 {
234 IntPtr ptr = new IntPtr();
235 Int32 rv = rrd_fetch(argv.GetUpperBound(0) + 1, argv, ref start, ref end, ref step, out ds_cnt,
236 out ptr, out data);
237 ds_namv = GetStringArray(ptr, ds_cnt);
238 return rv;
239 }
241 /// <summary>
242 /// Returns the timestamp of the first value in the rrd given the rra index
243 /// </summary>
244 /// <param name="filename">Full path to the rrd file</param>
245 /// <param name="rraindex">0 based index of the rra to get a value for</param>
246 /// <returns>Unix timestamp if successful, -1 if an error occurred</returns>
247 public static Int32 First(string filename, int rraindex)
248 {
249 return rrd_first_r(filename, rraindex);
250 }
252 /// <summary>
253 /// Returns the timestamp of the first value in the rrd
254 /// </summary>
255 /// <param name="argv">String array of command line arguments</param>
256 /// <returns>Unix timestamp if successful, -1 if an error occurred</returns>
257 public static Int32 First(string[] argv)
258 {
259 return rrd_first(argv.GetUpperBound(0) + 1, argv);
260 }
262 /// <summary>
263 /// Returns the timestamp of the last value in the rrd given the rra index
264 /// </summary>
265 /// <param name="filename"></param>
266 /// <param name="filename">Full path to the rrd file</param>
267 /// <param name="rraindex">0 based index of the rra to get a value for</param>
268 /// <returns>Unix timestamp if successful, -1 if an error occurred</returns>
269 public static Int32 Last(string filename, int rraindex)
270 {
271 return rrd_last_r(filename, rraindex);
272 }
274 /// <summary>
275 /// Returns the timestamp of the last value in the rrd
276 /// </summary>
277 /// <param name="argv">String array of command line arguments</param>
278 /// <returns>Unix timestamp if successful, -1 if an error occurred</returns>
279 public static Int32 Last(string[] argv)
280 {
281 return rrd_last(argv.GetUpperBound(0) + 1, argv);
282 }
284 /// <summary>
285 /// Finds the timestamp of the last updated value in the rrd
286 /// </summary>
287 /// <param name="filename">Full path to the rrd file</param>
288 /// <param name="ret_last_update">Unix timestamp of the last update</param>
289 /// <param name="ret_ds_count">Number of data sources found</param>
290 /// <param name="ret_ds_names">Names of the data sources found</param>
291 /// <param name="ret_last_ds">Name of the last data source found</param>
292 /// <returns>0 if successful, -1 if an error occurred</returns>
293 public static Int32 Last_Update(string filename, ref Int32 ret_last_update, ref UInt32 ret_ds_count,
294 ref string[] ret_ds_names, ref string[] ret_last_ds)
295 {
296 IntPtr ds_names = new IntPtr();
297 IntPtr last_ds = new IntPtr();
298 Int32 rt = rrd_lastupdate_r(filename, ref ret_last_update, ref ret_ds_count, out ds_names,out last_ds);
299 ret_ds_names = GetStringArray(ds_names, ret_ds_count);
300 ret_last_ds = GetStringArray(last_ds, 1);
301 return rt;
302 }
304 /// <summary>
305 /// Writes the contents of an rrd file to an XML file
306 /// </summary>
307 /// <param name="filename">Full path to the rrd file</param>
308 /// <param name="outname">Full path to write the XML output</param>
309 /// <returns>0 if successful, -1 if an error occurred</returns>
310 public static Int32 Dump(string filename, string outname)
311 {
312 return rrd_dump_r(filename, outname);
313 }
315 /// <summary>
316 /// Writes the contents of an rrd file to an XML file
317 /// </summary>
318 /// <param name="argv">String array of command line arguments</param>
319 /// <returns>0 if successful, -1 if an error occurred</returns>
320 public static Int32 Dump(string[] argv)
321 {
322 return rrd_dump(argv.GetUpperBound(0) + 1, argv);
323 }
325 /// <summary>
326 /// Grabs the values from an rrd. Similar to fetch but enables merging of multiple
327 /// rrds and calculations
328 /// </summary>
329 /// <param name="argv">String array of command line arguments</param>
330 /// <param name="start">Starting timestamp found in the rrd</param>
331 /// <param name="end">Ending timestamp found in the rrd</param>
332 /// <param name="step">Step size found in the rrd</param>
333 /// <param name="col_cnt">Number of data sources found in the rrd</param>
334 /// <param name="leggend_v">Add a legend</param>
335 /// <param name="data">Values from the rrd as double type</param>
336 /// <returns>0 if successful, -1 if an error occurred</returns>
337 public static Int32 Xport(string[] argv, ref Int32 start, ref Int32 end, ref UInt32 step,
338 ref UInt32 col_cnt, ref string[] legend_v, ref IntPtr data)
339 {
340 IntPtr legend = new IntPtr();
341 Int32 rt = rrd_xport(argv.GetUpperBound(0) + 1, argv, 0, ref start, ref end, ref step, ref col_cnt,
342 out legend, out data);
343 legend_v = GetStringArray(legend, col_cnt);
344 return rt;
345 }
347 /// <summary>
348 /// Creates an rrd from an XML data dump
349 /// </summary>
350 /// <param name="argv">String array of command line arguments</param>
351 /// <returns>0 if successful, -1 if an error occurred</returns>
352 public static Int32 Restore(string[] argv)
353 {
354 return rrd_restore(argv.GetUpperBound(0) + 1, argv);
355 }
357 /// <summary>
358 /// Alters the size of an RRA and creates a new rrd in the dll's directory
359 /// NOTE: The new rrd may return unexpected results if you are not very careful
360 /// NOTE: This may crash in version 1.4.3
361 /// </summary>
362 /// <param name="argv">String array of command line arguments</param>
363 /// <returns>0 if successful, -1 if an error occurred</returns>
364 public static Int32 Resize(string[] argv)
365 {
366 return rrd_resize(argv.GetUpperBound(0) + 1, argv);
367 }
369 /// <summary>
370 /// Modify the characteristics of an rrd
371 /// </summary>
372 /// <param name="argv">String array of command line arguments</param>
373 /// <returns>0 if successful, -1 if an error occurred</returns>
374 public static Int32 Tune(string[] argv)
375 {
376 return rrd_tune(argv.GetUpperBound(0) + 1, argv);
377 }
379 // UTILITIES
380 /// <summary>
381 /// Returns a string with the numeric version of the rrdlib build version
382 /// </summary>
383 /// <returns>A string with version information</returns>
384 public static string Version()
385 {
386 return rrd_strversion();
387 }
389 /// <summary>
390 /// Generates a random number for testing rrdlib
391 /// </summary>
392 /// <returns>A random integer</returns>
393 public static int Random()
394 {
395 return rrd_random();
396 }
398 /// <summary>
399 /// Returns the latest error from rrdlib
400 /// </summary>
401 /// <returns>A string with the error message, or an emtpy string if no error occurred</returns>
402 public static string Get_Error()
403 {
404 IntPtr ptr = rrd_get_error();
405 if (ptr == IntPtr.Zero)
406 return "";
407 return Marshal.PtrToStringAnsi(ptr);
408 }
410 /// <summary>
411 /// Formats and prints information in the object to the standard output
412 /// </summary>
413 /// <param name="info">rrd_info_t object with data to print</param>
414 public static void Info_Print(rrd_info_t info)
415 {
416 IntPtr newptr = Marshal.AllocHGlobal(Marshal.SizeOf(info));
417 Marshal.StructureToPtr(info, newptr, true);
418 rrd_info_print(newptr);
419 }
421 /// <summary>
422 /// Converts a Char ** array of characters from the RRDLib returned as an IntPtr and converts
423 /// it to a String array given the number of items in the ptr array.
424 /// Re: http://stackoverflow.com/questions/1498931/marshalling-array-of-strings-to-char-in-c-must-be-quite-easy-if-you-know-ho
425 /// </summary>
426 /// <param name="ptr">Pointer to a character array returned from the RRDLib</param>
427 /// <param name="size">Number of items in the character array (not the number of characters)</param>
428 /// <returns>A string array</returns>
429 private static string[] GetStringArray(IntPtr ptr, UInt32 size)
430 {
431 var list = new List<string>();
432 for (int i = 0; i < size; i++)
433 {
434 var strPtr = (IntPtr)Marshal.PtrToStructure(ptr, typeof(IntPtr));
435 list.Add(Marshal.PtrToStringAnsi(strPtr));
436 ptr = new IntPtr(ptr.ToInt64() + IntPtr.Size);
437 }
438 return list.ToArray();
439 }
440 }
441 }