| Class | Irc::Bot::Registry::Accessor |
| In: |
lib/rbot/registry/bdb.rb
lib/rbot/registry/tc.rb |
| Parent: | Object |
This class provides persistent storage for plugins via a hash interface. The default mode is an object store, so you can store ruby objects and reference them with hash keys. This is because the default store/restore methods of the plugins’ RegistryAccessor are calls to Marshal.dump and Marshal.restore, for example:
blah = Hash.new blah[:foo] = "fum" @registry[:blah] = blah
then, even after the bot is shut down and disconnected, on the next run you can access the blah object as it was, with:
blah = @registry[:blah]
The registry can of course be used to store simple strings, fixnums, etc as well, and should be useful to store or cache plugin data or dynamic plugin configuration.
WARNING: in object store mode, don‘t make the mistake of treating it like a live object, e.g. (using the example above)
@registry[:blah][:foo] = "flump"
will NOT modify the object in the registry - remember that Registry#[] returns a Marshal.restore‘d object, the object you just modified in place will disappear. You would need to:
blah = @registry[:blah] blah[:foo] = "flump" @registry[:blah] = blah
If you don‘t need to store objects, and strictly want a persistant hash of strings, you can override the store/restore methods to suit your needs, for example (in your plugin):
def initialize
class << @registry
def store(val)
val
end
def restore(val)
val
end
end
end
Your plugins section of the registry is private, it has its own namespace (derived from the plugin‘s class name, so change it and lose your data). Calls to registry.each etc, will only iterate over your namespace.
| recovery | [RW] | |
| recovery | [RW] |
plugins don‘t call this - a Registry::Accessor is created for them and is accessible via @registry.
# File lib/rbot/registry/bdb.rb, line 330
330: def initialize(bot, name)
331: @bot = bot
332: @name = name.downcase
333: @filename = @bot.path 'registry', @name
334: dirs = File.dirname(@filename).split("/")
335: dirs.length.times { |i|
336: dir = dirs[0,i+1].join("/")+"/"
337: unless File.exist?(dir)
338: debug "creating subregistry directory #{dir}"
339: Dir.mkdir(dir)
340: end
341: }
342: @filename << ".db"
343: @registry = nil
344: @default = nil
345: @recovery = nil
346: # debug "initializing registry accessor with name #{@name}"
347: end
plugins don‘t call this - a Registry::Accessor is created for them and is accessible via @registry.
# File lib/rbot/registry/tc.rb, line 305
305: def initialize(bot, name)
306: @bot = bot
307: @name = name.downcase
308: @filename = @bot.path 'registry', @name
309: dirs = File.dirname(@filename).split("/")
310: dirs.length.times { |i|
311: dir = dirs[0,i+1].join("/")+"/"
312: unless File.exist?(dir)
313: debug "creating subregistry directory #{dir}"
314: Dir.mkdir(dir)
315: end
316: }
317: @filename << ".tdb"
318: @registry = nil
319: @default = nil
320: @recovery = nil
321: # debug "initializing registry accessor with name #{@name}"
322: end
# File lib/rbot/registry/bdb.rb, line 360
360: def close
361: # debug "closing registry #{registry}"
362: return if !@registry
363: registry.close
364: end
# File lib/rbot/registry/tc.rb, line 334
334: def close
335: # debug "closing registry #{registry}"
336: return if !@registry
337: registry.close
338: end
# File lib/rbot/registry/tc.rb, line 396
396: def default
397: @default && (@default.dup rescue @default)
398: end
# File lib/rbot/registry/bdb.rb, line 422
422: def default
423: @default && (@default.dup rescue @default)
424: end
just like Hash#each
# File lib/rbot/registry/bdb.rb, line 427
427: def each(set=nil, bulk=0, &block)
428: return nil unless File.exist?(@filename)
429: registry.each(set, bulk) {|key,value|
430: block.call(key, restore(value))
431: }
432: end
just like Hash#each
# File lib/rbot/registry/tc.rb, line 401
401: def each(set=nil, bulk=0, &block)
402: return nil unless File.exist?(@filename)
403: registry.fwmkeys(set).each {|key|
404: block.call(key, restore(registry[key]))
405: }
406: end
just like Hash#each_key
# File lib/rbot/registry/tc.rb, line 409
409: def each_key(set=nil, bulk=0, &block)
410: return nil unless File.exist?(@filename)
411: registry.fwmkeys(set).each do |key|
412: block.call(key)
413: end
414: end
just like Hash#each_key
# File lib/rbot/registry/bdb.rb, line 435
435: def each_key(set=nil, bulk=0, &block)
436: return nil unless File.exist?(@filename)
437: registry.each_key(set, bulk) {|key|
438: block.call(key)
439: }
440: end
just like Hash#each_value
# File lib/rbot/registry/tc.rb, line 417
417: def each_value(set=nil, bulk=0, &block)
418: return nil unless File.exist?(@filename)
419: registry.fwmkeys(set).each do |key|
420: block.call(restore(registry[key]))
421: end
422: end
just like Hash#each_value
# File lib/rbot/registry/bdb.rb, line 443
443: def each_value(set=nil, bulk=0, &block)
444: return nil unless File.exist?(@filename)
445: registry.each_value(set, bulk) { |value|
446: block.call(restore(value))
447: }
448: end
# File lib/rbot/registry/bdb.rb, line 353
353: def flush
354: # debug "fushing registry #{registry}"
355: return if !@registry
356: registry.flush
357: registry.sync
358: end
# File lib/rbot/registry/tc.rb, line 328
328: def flush
329: # debug "fushing registry #{registry}"
330: return if !@registry
331: registry.sync
332: end
# File lib/rbot/registry/tc.rb, line 523
523: def getlist(key)
524: return [] unless File.exist?(@filename)
525: (registry.getlist(key.to_s) || []).map {|v| restore(v)}
526: end
just like Hash#has_both?
# File lib/rbot/registry/tc.rb, line 435
435: def has_both?(key, value)
436: return false unless File.exist?(@filename)
437: registry.has_key?(key.to_s) and registry.has_value?(store(value))
438: end
just like Hash#has_both?
# File lib/rbot/registry/bdb.rb, line 460
460: def has_both?(key, value)
461: return false unless File.exist?(@filename)
462: return registry.has_both?(key, store(value))
463: end
just like Hash#has_key?
# File lib/rbot/registry/bdb.rb, line 451
451: def has_key?(key)
452: return false unless File.exist?(@filename)
453: return registry.has_key?(key)
454: end
just like Hash#has_key?
# File lib/rbot/registry/tc.rb, line 425
425: def has_key?(key)
426: return false unless File.exist?(@filename)
427: return registry.has_key?(key.to_s)
428: end
just like Hash#has_value?
# File lib/rbot/registry/bdb.rb, line 466
466: def has_value?(value)
467: return false unless File.exist?(@filename)
468: return registry.has_value?(store(value))
469: end
just like Hash#has_value?
# File lib/rbot/registry/tc.rb, line 441
441: def has_value?(value)
442: return false unless File.exist?(@filename)
443: return registry.has_value?(store(value))
444: end
just like Hash#index?
# File lib/rbot/registry/tc.rb, line 447
447: def index(value)
448: self.each do |k,v|
449: return k if v == value
450: end
451: return nil
452: end
just like Hash#index?
# File lib/rbot/registry/bdb.rb, line 472
472: def index(value)
473: return nil unless File.exist?(@filename)
474: ind = registry.index(store(value))
475: if ind
476: return ind
477: else
478: return nil
479: end
480: end
That is btree!
# File lib/rbot/registry/tc.rb, line 515
515: def putdup(key, value)
516: registry.putdup(key.to_s, store(value))
517: end
# File lib/rbot/registry/tc.rb, line 519
519: def putlist(key, values)
520: registry.putlist(key.to_s, value.map {|v| store(v)})
521: end
# File lib/rbot/registry/tc.rb, line 324
324: def registry
325: @registry ||= DBTree.new @bot, "registry/#{@name}"
326: end
# File lib/rbot/registry/bdb.rb, line 349
349: def registry
350: @registry ||= DBTree.new @bot, "registry/#{@name}"
351: end
restores object from string form, restore(store(val)) must return val. If you override store, you should override restore to reverse the action. For example, if you always just handle strings use:
def restore(val)
val
end
# File lib/rbot/registry/tc.rb, line 358
358: def restore(val)
359: begin
360: Marshal.restore(val)
361: rescue Exception => e
362: error _("failed to restore marshal data for #{val.inspect}, attempting recovery or fallback to default")
363: debug e
364: if defined? @recovery and @recovery
365: begin
366: return @recovery.call(val)
367: rescue Exception => ee
368: error _("marshal recovery failed, trying default")
369: debug ee
370: end
371: end
372: return default
373: end
374: end
restores object from string form, restore(store(val)) must return val. If you override store, you should override restore to reverse the action. For example, if you always just handle strings use:
def restore(val)
val
end
# File lib/rbot/registry/bdb.rb, line 384
384: def restore(val)
385: begin
386: Marshal.restore(val)
387: rescue Exception => e
388: error _("failed to restore marshal data for #{val.inspect}, attempting recovery or fallback to default")
389: debug e
390: if defined? @recovery and @recovery
391: begin
392: return @recovery.call(val)
393: rescue Exception => ee
394: error _("marshal recovery failed, trying default")
395: debug ee
396: end
397: end
398: return default
399: end
400: end
convert value to string form for storing in the registry defaults to Marshal.dump(val) but you can override this in your module‘s registry object to use any method you like. For example, if you always just handle strings use:
def store(val)
val
end
# File lib/rbot/registry/tc.rb, line 347
347: def store(val)
348: Marshal.dump(val)
349: end
convert value to string form for storing in the registry defaults to Marshal.dump(val) but you can override this in your module‘s registry object to use any method you like. For example, if you always just handle strings use:
def store(val)
val
end
# File lib/rbot/registry/bdb.rb, line 373
373: def store(val)
374: Marshal.dump(val)
375: end
# File lib/rbot/registry/tc.rb, line 503
503: def sub_registry(prefix)
504: return Accessor.new(@bot, @name + "/" + prefix.to_s)
505: end
# File lib/rbot/registry/bdb.rb, line 531
531: def sub_registry(prefix)
532: return Accessor.new(@bot, @name + "/" + prefix.to_s)
533: end
Return an array of all associations [key, value] in your namespace
# File lib/rbot/registry/tc.rb, line 467
467: def to_a
468: return [] unless File.exist?(@filename)
469: ret = Array.new
470: registry.each {|key, value|
471: ret << [key, restore(value)]
472: }
473: return ret
474: end
Return an array of all associations [key, value] in your namespace
# File lib/rbot/registry/bdb.rb, line 495
495: def to_a
496: return [] unless File.exist?(@filename)
497: ret = Array.new
498: registry.each {|key, value|
499: ret << [key, restore(value)]
500: }
501: return ret
502: end
Return an hash of all associations {key => value} in your namespace
# File lib/rbot/registry/bdb.rb, line 505
505: def to_hash
506: return {} unless File.exist?(@filename)
507: ret = Hash.new
508: registry.each {|key, value|
509: ret[key] = restore(value)
510: }
511: return ret
512: end
Return an hash of all associations {key => value} in your namespace
# File lib/rbot/registry/tc.rb, line 477
477: def to_hash
478: return {} unless File.exist?(@filename)
479: ret = Hash.new
480: registry.each {|key, value|
481: ret[key] = restore(value)
482: }
483: return ret
484: end