class RRD::Wrapper

Raw RRD Tool wrapper.

See oss.oetiker.ch/rrdtool/doc/rrdtool.en.html for details on the parameters

Constants

BANG_METHODS
INFO_TYPE

Public Class Methods

bang(method, *args, &block) click to toggle source
# File lib/rrd/wrapper.rb, line 368
def bang(method, *args, &block)
  result = send(method, *args, &block)
  raise error unless result
  result
end
clear_error() click to toggle source

Clear the error message.

# File lib/rrd/wrapper.rb, line 360
def clear_error
  rrd_clear_error
end
create(*args) click to toggle source

Set up a new Round Robin Database (RRD).

# File lib/rrd/wrapper.rb, line 83
def create(*args)
  argv = to_pointer(["create"] + args)
  rrd_create(args.size+1, argv) == 0
ensure
  free_pointers
end
detect_rrd_lib() click to toggle source
# File lib/rrd/wrapper.rb, line 10
def self.detect_rrd_lib
  if defined?(RRD_LIB)
    RRD_LIB
  elsif ENV["RRD_LIB"]
    ENV["RRD_LIB"] 
  else
    "rrd"
  end
end
dump(*args) click to toggle source

Dump a binary RRD to an RRD in XML format.

# File lib/rrd/wrapper.rb, line 91
def dump(*args)
  argv = to_pointer(["dump"] + args)
  rrd_dump(args.size+1, argv) == 0
ensure
  free_pointers
end
error() click to toggle source

Returns the error happened.

# File lib/rrd/wrapper.rb, line 355
def error
  rrd_get_error
end
fetch(*args) click to toggle source

Get data for a certain time period from a RRD.

Returns an array of arrays (which contains the date and values for all datasources):

[["time"    , "cpu", "memory"],
 [1266933600, "0.5", "511"   ],
 [1266933900, "0.9", "253"   ]]
# File lib/rrd/wrapper.rb, line 106
def fetch(*args)
  #FIXME: Refactor this
  start_time_ptr = empty_pointer
  end_time_ptr = empty_pointer
  step_ptr = empty_pointer
  ds_count_ptr = empty_pointer
  ds_names_ptr = empty_pointer
  values_ptr = empty_pointer
  
  argv = to_pointer(["fetch"] + args)
  if respond_to?(:rrd_fetch_r)
    file = args[0]
    cf = args[1]
    options = {}
    args[2..-1].each_slice(2) {|v| options[v.first] = v.last}
    start_time = options["--start"]
    end_time = options["--end"]
    step = options["--resolution"]
    start_time_ptr.put_int(0, start_time.to_i)
    end_time_ptr.put_int(0, end_time.to_i)
    step_ptr.put_int(0, step.to_i)
    return false unless rrd_fetch_r(file, cf, start_time_ptr, end_time_ptr, step_ptr, ds_count_ptr, ds_names_ptr, values_ptr) == 0
  else
    return false unless rrd_fetch(args.size+1, argv, start_time_ptr, end_time_ptr, step_ptr, ds_count_ptr, ds_names_ptr, values_ptr) == 0
  end
  
  ds_count = ds_count_ptr.get_int(0)
  start_time = start_time_ptr.get_int(0)
  end_time = end_time_ptr.get_int(0)
  step = step_ptr.get_int(0)
  
  result_lines = (end_time-start_time)/step
  
  ds_names = ds_names_ptr.get_pointer(0).get_array_of_string(0, ds_count)
  values = values_ptr.get_pointer(0).get_array_of_double(0, result_lines * ds_count)
  
  result = [["time"] + ds_names]
  (0..result_lines-1).each do |line|
    date = start_time + line*step
    first = ds_count*line
    last = ds_count*line + ds_count - 1
    result << [date] + values[first..last]
  end
  
  free_in_rrd(*ds_names_ptr.read_pointer.read_array_of_pointer(ds_count))
  free_in_rrd(values_ptr.read_pointer, ds_names_ptr.read_pointer)
  
  result
ensure
  free_pointers
end
first(*args) click to toggle source

Find the first update time of an RRD.

Returns an integer unix time

# File lib/rrd/wrapper.rb, line 220
def first(*args)
  argv = to_pointer(["first"] + args)
  date = rrd_first(args.size+1, argv)
  return false if date == -1
  date
ensure
  free_pointers
end
graph(*args) click to toggle source

Create a graph from data stored in one or several RRDs.

# File lib/rrd/wrapper.rb, line 230
def graph(*args)
  warn('Your RRDTool version contains a memory leak on rrd_graph function. Please, use carefully!') if ('1.3' <= rrd_strversion && rrd_strversion <= '1.4.2')
  argv = to_pointer(["graph"] + args)
  calcpr_ptr = empty_pointer
  xsize_ptr = empty_pointer
  ysize_ptr = empty_pointer
  ymin_ptr = empty_pointer
  ymax_ptr = empty_pointer
  result = rrd_graph(args.size+1, argv, calcpr_ptr, xsize_ptr, ysize_ptr, nil, ymin_ptr, ymax_ptr) == 0
  
  if (!calcpr_ptr.read_pointer.null?)
    iter = calcpr_ptr.read_pointer
    until ((pointer = iter.read_pointer).null?)
      iter += FFI::Type::POINTER.size
      free_in_rrd(pointer)
    end
    free_in_rrd(calcpr_ptr.read_pointer)
  end
  
  result
ensure
  free_pointers
end
info(*args) click to toggle source

Get information about an RRD.

Returns a hash with the information

# File lib/rrd/wrapper.rb, line 257
def info(*args)
  argv = to_pointer(["info"] + args)
  ptr = result_ptr = rrd_info(args.size+1, argv)
    
  info = {}
  while result_ptr.address != 0
    item = RRD::Wrapper::RRDInfo.new result_ptr
    info[item[:key]] = item[:value][INFO_TYPE[item[:type]].to_sym]
    result_ptr = item[:next]
  end
  
  rrd_info_free(ptr)
  
  return false if info.empty?
  info
  
ensure
  free_pointers
end
last(*args) click to toggle source

Find the last update time of an RRD.

Returns an integer unix time

# File lib/rrd/wrapper.rb, line 280
def last(*args)
  argv = to_pointer(["last"] + args)
  date = rrd_last(args.size+1, argv)
  return false if date == -1
  date
ensure
  free_pointers
end
last_update(file) click to toggle source

Get the last entered data.

Returns an array of 2 arrays (one with datasource names and other with the values):

[["time"    , "cpu", "memory"],
 [1266933900, "0.9", "253"   ]]
# File lib/rrd/wrapper.rb, line 296
def last_update(file)
  raise "Please upgrade your rrdtool version before using last_update method" unless respond_to?(:rrd_lastupdate_r)
  update_time_ptr = empty_pointer
  ds_count_ptr = empty_pointer
  ds_names_ptr = empty_pointer
  values_ptr = empty_pointer
  
  return false if rrd_lastupdate_r(file, update_time_ptr, ds_count_ptr, ds_names_ptr, values_ptr) == -1
  update_time = update_time_ptr.get_ulong(0)
  ds_count = ds_count_ptr.get_ulong(0)
  ds_names = ds_names_ptr.read_pointer.get_array_of_string(0, ds_count)
  values = values_ptr.read_pointer.get_array_of_string(0, ds_count)
  values = values.map {|item| item.include?(".")? item.to_f : item.to_i} # Converting string to numeric

  free_in_rrd(*ds_names_ptr.read_pointer.read_array_of_pointer(ds_count))
  free_in_rrd(*values_ptr.read_pointer.read_array_of_pointer(ds_count))
  free_in_rrd(ds_names_ptr.read_pointer, values_ptr.read_pointer)

  [["time"] + ds_names, [update_time]+values]
ensure
  # free_pointers
end
methods() click to toggle source
Calls superclass method
# File lib/rrd/wrapper.rb, line 364
def methods
  super + BANG_METHODS
end
resize(*args) click to toggle source

Used to modify the number of rows in an RRA

Creates a new file in the same directory, called 'resize.rrd'

# File lib/rrd/wrapper.rb, line 322
def resize(*args)
  argv = to_pointer(["resize"] + args)
  rrd_resize(args.size+1, argv) == 0
ensure
  free_pointers
end
restore(*args) click to toggle source

Restore an RRD in XML format to a binary RRD.

# File lib/rrd/wrapper.rb, line 330
def restore(*args)
  argv = to_pointer(["restore"] + args)
  rrd_restore(args.size+1, argv) == 0
ensure
  free_pointers
end
tune(*args) click to toggle source

Allows you to alter some of the basic configuration values stored in the header area of a Round Robin Database.

# File lib/rrd/wrapper.rb, line 339
def tune(*args)
  argv = to_pointer(["tune"] + args)
  rrd_tune(args.size+1, argv) == 0
ensure
  free_pointers
end
update(*args) click to toggle source

Store new data values into an RRD.

# File lib/rrd/wrapper.rb, line 347
def update(*args)
  argv = to_pointer(["update"] + args)
  rrd_update(args.size+1, argv) == 0
ensure
  free_pointers
end
xport(*args) click to toggle source

int rrd_xport(

int argc,
char **argv,
int UNUSED(*xsize),
time_t *start,
time_t *end,           which time frame do you want ?
                       will be changed to represent reality   
unsigned long *step,       which stepsize do you want? 
                           will be changed to represent reality   
unsigned long *col_cnt, /* number of data columns in the result */
char ***legend_v,   /* legend entries */
rrd_value_t **data)
# File lib/rrd/wrapper.rb, line 171
def xport(*args)
  start_time_ptr = empty_pointer
  end_time_ptr = empty_pointer
  step_ptr = empty_pointer
  legend_count_ptr = empty_pointer
  legend_names_ptr = empty_pointer
  values_ptr = empty_pointer
  
  i_am_useless = empty_pointer
  
  
  argv = to_pointer(["xport"] + args)
  ret = rrd_xport(args.size+1, argv,
    i_am_useless, start_time_ptr, end_time_ptr, step_ptr,
    legend_count_ptr, legend_names_ptr, values_ptr)
  
  return false unless ret == 0
  
  
  legends_count = legend_count_ptr.get_int(0)
  start_time = start_time_ptr.get_int(0)
  end_time = end_time_ptr.get_int(0)
  step = step_ptr.get_int(0)
  
  result_lines = (end_time-start_time)/step
  
  legends = legend_names_ptr.get_pointer(0).get_array_of_string(0, legends_count)
  values = values_ptr.get_pointer(0).get_array_of_double(0, result_lines * legends_count)
  
  result = [["time"] + legends]
  (0..result_lines-1).each do |line|
    date = start_time + line*step
    first = legends_count*line
    last = legends_count*line + legends_count - 1
    result << [date] + values[first..last]
  end
  
  free_in_rrd(*legend_names_ptr.read_pointer.read_array_of_pointer(legends_count))
  free_in_rrd(values_ptr.read_pointer, legend_names_ptr.read_pointer)
  
  result
  
ensure
  free_pointers
end

Private Class Methods

empty_pointer() click to toggle source
# File lib/rrd/wrapper.rb, line 385
def empty_pointer
  mem_ptrs ||= []
  ptr = FFI::MemoryPointer.new(:pointer)
  mem_ptrs << ptr
  ptr
end
free_in_rrd(*pointers) click to toggle source
# File lib/rrd/wrapper.rb, line 406
def free_in_rrd(*pointers)
  pointers.each{|pointer| rrd_freemem(pointer)}
end
free_pointers() click to toggle source
# File lib/rrd/wrapper.rb, line 410
def free_pointers
  str_ptrs ||= []
  mem_ptrs ||= []
  
  str_ptrs.each{|str_ptr| str_ptr.free}
  mem_ptrs.each{|mem_ptr| mem_ptr.free}
  argv.free unless argv.nil?
  
  argv = nil
  str_ptrs = nil
  mem_ptrs = nil
end
to_pointer(array_of_strings) click to toggle source

FIXME: remove ::clear_error from here

# File lib/rrd/wrapper.rb, line 393
def to_pointer(array_of_strings)
  clear_error
  str_ptrs = []
  array_of_strings.each {|item| str_ptrs << FFI::MemoryPointer.from_string(item)}

  argv = FFI::MemoryPointer.new(:pointer, str_ptrs.length)
  str_ptrs.each_with_index do |p, i|
    argv[i].put_pointer(0,  p)
  end

  argv
end