class Agama::Graph
Public Class Methods
new(params)
click to toggle source
Initialises variables and sets the path
# File lib/agama/graph.rb, line 6 def initialize(params) @db_path = params[:path] || "./" @db = params[:db] end
Public Instance Methods
clean_edge(edge)
click to toggle source
# File lib/agama/graph.rb, line 254 def clean_edge(edge) new_edge = {} edge.each do |key, value| next if (key == :type or key == :from or key == :to or key == :directed) new_edge[key] = value end return new_edge end
clean_node(node)
click to toggle source
Methods to seperate key from the value
# File lib/agama/graph.rb, line 244 def clean_node(node) new_node = {} node.each do |key, value| next if (key == :type or key == :name) new_node[key] = value end return new_node end
close()
click to toggle source
Closes the database connection
# File lib/agama/graph.rb, line 29 def close @db.close end
edge_count(type = nil)
click to toggle source
# File lib/agama/graph.rb, line 230 def edge_count(type = nil) if type value = @db.m_get("edge#{type}") if value etype = Marshal.load(value) etype[:count] end else Marshal.load(@db.m_get("m")) end end
get_edge(edge)
click to toggle source
Fetches the value assigned to the edge from the from node to the to node
# File lib/agama/graph.rb, line 148 def get_edge(edge) return nil unless edge[:from][:name] return nil unless edge[:to][:name] #Get the type of the edge type = edge[:type] || Config::DEFAULT_TYPE edge[:type] = type #Check if the edge type exists etype = Marshal.load(@db.m_get("edge#{type}")) if @db.m_get("edge#{type}") #Integrity check: Check whether the edge direction is not contradictory if edge[:directed] if etype if etype[:directed] != edge[:directed] return false end else #If there is no edge of that type then pre-empt the result return false end else if etype edge[:directed] = etype[:directed] else #If there is no edge of that type then pre-empt the result return false end end #Convert the edge into a Key string and fetch the corresponding data key, reverse_key = Keyify.edge(edge) value = @db.e_get(key) if value new_edge = Marshal.load(value) new_edge[:from] = self.get_node(edge[:from]) new_edge[:to] = self.get_node(edge[:to]) new_edge[:type] = edge[:type] new_edge[:directed] = etype[:directed] #Pick direction alone from the meta_db for consistency new_edge end end
get_node(node)
click to toggle source
Fetches the node requested
# File lib/agama/graph.rb, line 71 def get_node(node) return nil unless node[:name] #Convert the node into a Key string and fetch the corresponding data key = Keyify.node(node) value = @db.n_get(key) if value new_node = Marshal.load(value) new_node[:name] = node[:name] new_node[:type] = node[:type] || Config::DEFAULT_TYPE new_node end end
neighbours(node)
click to toggle source
# File lib/agama/graph.rb, line 192 def neighbours(node) traverser = Traverser.new(@db, self) traverser.set(:from => node) end
node_count(type = nil)
click to toggle source
Accessors for meta values
# File lib/agama/graph.rb, line 219 def node_count(type = nil) if type value = @db.m_get("node#{type}") if value Marshal.load(value) end else Marshal.load(@db.m_get("n")) end end
open()
click to toggle source
Opens the database for access
# File lib/agama/graph.rb, line 13 def open @db.open(@db_path) #Create meta variables if they are absent unless @db.m_get("n") @db.m_put("n", Marshal.dump(0)) #Total node count @db.m_put("m", Marshal.dump(0)) #Total edge count @db.m_put("node#{Config::DEFAULT_TYPE}", Marshal.dump(0)) #Node count for default type @db.m_put("edge#{Config::DEFAULT_TYPE}", Marshal.dump({:directed => false, :count => 0})) #Edge count for default type end end
set_edge(edge)
click to toggle source
Creates/Updates an edge
# File lib/agama/graph.rb, line 88 def set_edge(edge) return false unless edge return false unless edge[:from][:name] return false unless edge[:to][:name] #Get the type of the edge type = edge[:type] || Config::DEFAULT_TYPE edge[:type] = type #Check if the edge type exists etype = Marshal.load(@db.m_get("edge#{type}")) if @db.m_get("edge#{type}") #Integrity check: Check whether the edge direction is not contradictory if edge[:directed] if etype if etype[:directed] != edge[:directed] raise "Edge creation error: edge direction contradicting existing edges" return end end else if etype edge[:directed] = etype[:directed] else edge[:directed] = false end end #Convert the edge into Key, Reversed Key and Value strings for storage key, reverse_key = Keyify.edge(edge) value = Marshal.dump(clean_edge(edge)) #Integrity check: Check if the incident nodes are defined unless (self.get_node(edge[:from]) and self.get_node(edge[:to])) raise "Edge creation error: node(s) not defined" return end #Check whether the operation is an insert (not an update), if so increment count unless @db.e_get(key) if etype etype[:count] += 1 @db.m_put("edge#{type}", Marshal.dump(etype)) else @db.m_put("edge#{type}", Marshal.dump({:directed => edge[:directed], :count => 1})) end #Increment global count @db.m_put("m", Marshal.dump(Marshal.load(@db.m_get("m")) + 1)) end #Add the edge and the reversed edge if @db.e_put(key, value) and @db.e_put(reverse_key, value) return edge end end
set_node(node)
click to toggle source
Creates/Updates a node
# File lib/agama/graph.rb, line 35 def set_node(node) return nil unless node[:name] #Get the type of the node type = node[:type] || Config::DEFAULT_TYPE node[:type] = type #Convert the node into Key and Value strings for storage key = Keyify.node(node) value = Marshal.dump(self.clean_node(node)) #remove key items from value #Check if the node type exists, and if so get its count count = Marshal.load(@db.m_get("node#{type}")) if @db.m_get("node#{type}") #Check whether the operation is an insert (not an update), if so increment count unless @db.n_get(key) #Increment type-specific count if count count += 1 @db.m_put("node#{type}", Marshal.dump(count)) else @db.m_put("node#{type}", Marshal.dump(1)) end #Increment global count @db.m_put("n", Marshal.dump(Marshal.load(@db.m_get("n")) + 1)) end #Store the node if @db.n_put(key, value) node end end