class LibRebl
Library of functions used by rebl. More generally, this can be viewed as a way to have a bud class that you can add and remove rules from, and that you can step through the execution of.
Attributes
ip[R]
port[R]
rebl_class_inst[R]
rules[RW]
state[RW]
Public Class Methods
new(ip, port)
click to toggle source
# File lib/bud/rebl.rb, line 215 def initialize(ip, port) @ip = ip @port = port @rules = {} @ruleid = 0 @state = {} @stateid = 0 @rebl_class = nil @rebl_class_inst = nil @old_inst = nil reinstantiate end
Public Instance Methods
add_collection(c)
click to toggle source
Declares a new collection.
# File lib/bud/rebl.rb, line 259 def add_collection(c) @state[@stateid += 1] = c begin reinstantiate rescue Exception @state.delete(@stateid) raise end end
add_rule(r)
click to toggle source
Adds a new rule at the current time; only derives tuples based on data that exists at the current or a future time.
# File lib/bud/rebl.rb, line 282 def add_rule(r) @rules[@ruleid += 1] = r begin reinstantiate rescue Exception @rules.delete(@ruleid) raise end end
del_rule(rid)
click to toggle source
Deactivates a rule at the current time; any tuples derived by the rule at a previous time are still available.
# File lib/bud/rebl.rb, line 271 def del_rule(rid) unless @rules.has_key? rid puts "No rule with ID #{rid}" return end @rules.delete(rid) reinstantiate end
dump(c)
click to toggle source
Dumps the contents of a table at the current time.
# File lib/bud/rebl.rb, line 244 def dump(c) if c.nil? puts "Error: dump must be passed a collection name" elsif @rebl_class_inst.tables.has_key? c.to_sym tups = @rebl_class_inst.tables[c.to_sym].to_a.sort puts(tups.empty? ? "(empty)" : tups.sort.map{|t| "#{t}"}.join("\n")) elsif @rebl_class_inst.lattices.has_key? c.to_sym val = @rebl_class_inst.lattices[c.to_sym].current_value puts val.inspect else puts "Error: non-existent collection \"#{c}\"" end end
mk_rebl_class()
click to toggle source
# File lib/bud/rebl.rb, line 292 def mk_rebl_class @@classid += 1 cls_name = "ReblClass#{@@classid}" str = "" str =<<-EOS $BUD_SAFE=1 class #{cls_name} < ReblBase include Bud EOS unless @state.empty? str += "state do\n" + @state.values.join("\n") + "\nend\n" end unless @rules.empty? str += "bloom :rebl_rules do\n" + @rules.sort.map {|_,r| r}.join("\n") + "\nend\n" end str += "\nend\n" f = Tempfile.new("rebl") f.write(str) f.close begin load f.path return eval cls_name # return the class object rescue $stderr.puts "Unable to eval the following code:\n" + str raise ensure f.unlink end end
run()
click to toggle source
Runs the bud instance (until a breakpoint, or stop() is called)
# File lib/bud/rebl.rb, line 229 def run @rebl_class_inst.run_bg end
stop()
click to toggle source
Stops the bud instance (and then performs another tick)
# File lib/bud/rebl.rb, line 234 def stop @rebl_class_inst.pause end
tick(x=1)
click to toggle source
Ticks the bud instance a specified integer number of times.
# File lib/bud/rebl.rb, line 239 def tick(x=1) x.times {@rebl_class_inst.sync_do} end
Private Instance Methods
reinstantiate()
click to toggle source
# File lib/bud/rebl.rb, line 324 def reinstantiate @rebl_class = mk_rebl_class @old_inst = @rebl_class_inst @rebl_class_inst = @rebl_class.new(:signal_handling => :none, :ip => @ip, :port => @port) # Stop the old instance. We want to copy the old instance's state over to # the new instance and then startup the new instance. Any network messages # received before the new instance has been started will be lost, but that # can't easily be avoided; the best we can do is ensure we get a consistent # snapshot of the old instance's state. @old_inst.stop if @old_inst # Copy the tables over. if @old_inst @rebl_class_inst.tables.merge!(@old_inst.tables.reject do |k,v| @@builtin_tables.include? k end) @rebl_class_inst.tables.each do |k,v| v.invalidate_cache end @rebl_class_inst.channels.merge!(@old_inst.channels.reject do |k,v| @@builtin_tables.include? k end) @rebl_class_inst.dbm_tables.merge! @old_inst.dbm_tables @rebl_class_inst.zk_tables.merge! @old_inst.zk_tables @rebl_class_inst.lattices.merge! @old_inst.lattices # Fix the bud instance pointers from copied tables. @rebl_class_inst.tables.each_value do |v| v.bud_instance = @rebl_class_inst end @rebl_class_inst.lattices.each_value do |v| v.bud_instance = @rebl_class_inst end end # Run lazily in background, shutting down old instance. begin # Lazify the instance upon a breakpoint (no effect if instance is # already lazy) @rebl_class_inst.register_callback(:rebl_breakpoint) do @rebl_class_inst.pause end @rebl_class_inst.start @ip = @rebl_class_inst.ip @port = @rebl_class_inst.port puts "Listening on #{@ip}:#{@port}" unless @old_inst rescue Exception # The above two need to be atomic, or we're in trouble. puts "unrecoverable error, please file a bug: #{$!}" abort end end