Class: Irc::Bot::Registry::Accessor

Inherits:
Object
  • Object
show all
Defined in:
lib/rbot/registry/tc.rb,
lib/rbot/registry/bdb.rb

Overview

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.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(bot, name) ⇒ Accessor

plugins don’t call this - a Registry::Accessor is created for them and is accessible via @registry.



305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
# File 'lib/rbot/registry/tc.rb', line 305

def initialize(bot, name)
  @bot = bot
  @name = name.downcase
  @filename = @bot.path 'registry', @name
  dirs = File.dirname(@filename).split("/")
  dirs.length.times { |i|
    dir = dirs[0,i+1].join("/")+"/"
    unless File.exist?(dir)
      debug "creating subregistry directory #{dir}"
      Dir.mkdir(dir)
    end
  }
  @filename << ".tdb"
  @registry = nil
  @default = nil
  @recovery = nil
  # debug "initializing registry accessor with name #{@name}"
end

Instance Attribute Details

#recoveryObject

Returns the value of attribute recovery.



301
302
303
# File 'lib/rbot/registry/tc.rb', line 301

def recovery
  @recovery
end

Instance Method Details

#[](key) ⇒ Object

lookup a key in the registry



377
378
379
380
381
382
383
# File 'lib/rbot/registry/tc.rb', line 377

def [](key)
  if File.exist?(@filename) and registry.has_key?(key.to_s)
    return restore(registry[key.to_s])
  else
    return default
  end
end

#[]=(key, value) ⇒ Object

set a key in the registry



386
387
388
# File 'lib/rbot/registry/tc.rb', line 386

def []=(key,value)
  registry[key.to_s] = store(value)
end

#clearObject Also known as: truncate

empties the registry (restricted to your namespace)



487
488
489
490
# File 'lib/rbot/registry/tc.rb', line 487

def clear
  return true unless File.exist?(@filename)
  registry.vanish
end

#closeObject



334
335
336
337
338
# File 'lib/rbot/registry/tc.rb', line 334

def close
  # debug "closing registry #{registry}"
  return if !@registry
  registry.close
end

#defaultObject



396
397
398
# File 'lib/rbot/registry/tc.rb', line 396

def default
  @default && (@default.dup rescue @default)
end

#delete(key) ⇒ Object

delete a key from the registry



455
456
457
458
# File 'lib/rbot/registry/tc.rb', line 455

def delete(key)
  return default unless File.exist?(@filename)
  return registry.delete(key.to_s)
end

#each(set = nil, bulk = 0, &block) ⇒ Object

just like Hash#each



401
402
403
404
405
406
# File 'lib/rbot/registry/tc.rb', line 401

def each(set=nil, bulk=0, &block)
  return nil unless File.exist?(@filename)
  registry.fwmkeys(set).each {|key|
    block.call(key, restore(registry[key]))
  }
end

#each_key(set = nil, bulk = 0, &block) ⇒ Object

just like Hash#each_key



409
410
411
412
413
414
# File 'lib/rbot/registry/tc.rb', line 409

def each_key(set=nil, bulk=0, &block)
  return nil unless File.exist?(@filename)
  registry.fwmkeys(set).each do |key|
    block.call(key)
  end
end

#each_value(set = nil, bulk = 0, &block) ⇒ Object

just like Hash#each_value



417
418
419
420
421
422
# File 'lib/rbot/registry/tc.rb', line 417

def each_value(set=nil, bulk=0, &block)
  return nil unless File.exist?(@filename)
  registry.fwmkeys(set).each do |key|
    block.call(restore(registry[key]))
  end
end

#flushObject



328
329
330
331
332
# File 'lib/rbot/registry/tc.rb', line 328

def flush
  # debug "fushing registry #{registry}"
  return if !@registry
  registry.sync
end

#getlist(key) ⇒ Object



523
524
525
526
# File 'lib/rbot/registry/tc.rb', line 523

def getlist(key)
  return [] unless File.exist?(@filename)
  (registry.getlist(key.to_s) || []).map {|v| restore(v)}
end

#has_both?(key, value) ⇒ Boolean

just like Hash#has_both?

Returns:

  • (Boolean)


435
436
437
438
# File 'lib/rbot/registry/tc.rb', line 435

def has_both?(key, value)
  return false unless File.exist?(@filename)
  registry.has_key?(key.to_s) and registry.has_value?(store(value))
end

#has_key?(key) ⇒ Boolean Also known as: include?, member?, key?

just like Hash#has_key?

Returns:

  • (Boolean)


425
426
427
428
# File 'lib/rbot/registry/tc.rb', line 425

def has_key?(key)
  return false unless File.exist?(@filename)
  return registry.has_key?(key.to_s)
end

#has_value?(value) ⇒ Boolean

just like Hash#has_value?

Returns:

  • (Boolean)


441
442
443
444
# File 'lib/rbot/registry/tc.rb', line 441

def has_value?(value)
  return false unless File.exist?(@filename)
  return registry.has_value?(store(value))
end

#index(value) ⇒ Object

just like Hash#index?



447
448
449
450
451
452
# File 'lib/rbot/registry/tc.rb', line 447

def index(value)
  self.each do |k,v|
    return k if v == value
  end
  return nil
end

#keysObject

returns a list of your keys



461
462
463
464
# File 'lib/rbot/registry/tc.rb', line 461

def keys
  return [] unless File.exist?(@filename)
  return registry.keys
end

#lengthObject Also known as: size

returns the number of keys in your registry namespace



508
509
510
511
# File 'lib/rbot/registry/tc.rb', line 508

def length
  return 0 unless File.exist?(@filename)
  registry.length
end

#putdup(key, value) ⇒ Object

That is btree!



515
516
517
# File 'lib/rbot/registry/tc.rb', line 515

def putdup(key, value)
  registry.putdup(key.to_s, store(value))
end

#putlist(key, values) ⇒ Object



519
520
521
# File 'lib/rbot/registry/tc.rb', line 519

def putlist(key, values)
  registry.putlist(key.to_s, value.map {|v| store(v)})
end

#registryObject



324
325
326
# File 'lib/rbot/registry/tc.rb', line 324

def registry
    @registry ||= DBTree.new @bot, "registry/#{@name}"
end

#restore(val) ⇒ Object

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


358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
# File 'lib/rbot/registry/tc.rb', line 358

def restore(val)
  begin
    Marshal.restore(val)
  rescue Exception => e
    error _("failed to restore marshal data for #{val.inspect}, attempting recovery or fallback to default")
    debug e
    if defined? @recovery and @recovery
      begin
        return @recovery.call(val)
      rescue Exception => ee
        error _("marshal recovery failed, trying default")
        debug ee
      end
    end
    return default
  end
end

#set_default(default) ⇒ Object

set the default value for registry lookups, if the key sought is not found, the default will be returned. The default default (har) is nil.



392
393
394
# File 'lib/rbot/registry/tc.rb', line 392

def set_default (default)
  @default = default
end

#store(val) ⇒ Object

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


347
348
349
# File 'lib/rbot/registry/tc.rb', line 347

def store(val)
  Marshal.dump(val)
end

#sub_registry(prefix) ⇒ Object



503
504
505
# File 'lib/rbot/registry/tc.rb', line 503

def sub_registry(prefix)
  return Accessor.new(@bot, @name + "/" + prefix.to_s)
end

#to_aObject

Return an array of all associations [key, value] in your namespace



467
468
469
470
471
472
473
474
# File 'lib/rbot/registry/tc.rb', line 467

def to_a
  return [] unless File.exist?(@filename)
  ret = Array.new
  registry.each {|key, value|
    ret << [key, restore(value)]
  }
  return ret
end

#to_hashObject

Return an hash of all associations => value in your namespace



477
478
479
480
481
482
483
484
# File 'lib/rbot/registry/tc.rb', line 477

def to_hash
  return {} unless File.exist?(@filename)
  ret = Hash.new
  registry.each {|key, value|
    ret[key] = restore(value)
  }
  return ret
end

#valuesObject

returns an array of the values in your namespace of the registry



494
495
496
497
498
499
500
501
# File 'lib/rbot/registry/tc.rb', line 494

def values
  return [] unless File.exist?(@filename)
  ret = Array.new
  self.each {|k,v|
    ret << restore(v)
  }
  return ret
end