| Class | MUES::ObjectStore::DBIBackend |
| In: |
lib/mues/os-extensions/dbibackend.rb
(CVS)
|
| Parent: | Backend |
RDBMS ObjectStore backend via DBI.
| SVNRev | = | %q$Rev: 1206 $ | SVN Revision | |
| SVNId | = | %q$Id: dbibackend.rb 1206 2004-05-09 21:25:11Z deveiant $ | SVN Id | |
| SVNURL | = | %q$URL: svn+ssh://deveiate.org/usr/local/svn/MUES/trunk/lib/mues/os-extensions/dbibackend.rb $ | SVN URL | |
| DefaultConfig | = | { :username => 'mues', :password => 'mues', :preconnect => true, } | The default settings to use when connecting. |
Create a new DBIBackend object, where the specified name is the DSN of the database to use. If the database does not already exist, it will be created. The config should contain the username and the password to use when connecting (:username and :password keys) and any other settings used by the adapter for the DBD specified by the DSN.
# File lib/mues/os-extensions/dbibackend.rb, line 91 def initialize( name, indexes=[], config=DefaultConfig ) checkType( indexes, ::Array ) checkType( config, ::Hash ) @dsn = name.to_s @indexes = indexes @config = config @username = config[:username] || DefaultConfig[:username] @password = config[:password] || DefaultConfig[:password] @adapter = nil @tablesUpToDate = false @indexesUpToDate = false self.log.debug "Connecting to '%s' as '%s'..." % [ @dsn, @username ] @adapter = self.getAdapter( @dsn, @username, @password ) return true end
Add the specified indexes, which are Strings or Symbols that represent methods to call on stored objects.
# File lib/mues/os-extensions/dbibackend.rb, line 317 def addIndexes( *indexes ) checkOpened() indexes.each {|idx| indexName = idx.to_s idx = indexName.intern self.log.debug {"Adding index '#{indexName}'"} # Open a secondary handle and associate it with the first, # along with a proc for making the index value from a key => # value pair. @indexes[idx] = @env.open_db( BDB::Hash, indexName + "_i", nil, BDB::CREATE, :set_flags => BDB::DUP|BDB::DUPSORT, :marshal => ::Marshal ) @db.associate( @indexes[idx], BDB::CREATE ) {|db,key,value| # :TODO: This should be taken out of production code unless value.is_a? MUES::StorableObject $stderr.puts "Ack! Value in indexer proc is not a StorableObject," + "but a #{value.class.name}!" end if value.respond_to?( idx ) value.send( idx ) else false end } } end
Close the backend
# File lib/mues/os-extensions/dbibackend.rb, line 278 def close checkOpened() @open = false @indexes.each_value {|idx| idx.close} @db.close @env.close end
Return an Array of keys for the specified index.
# File lib/mues/os-extensions/dbibackend.rb, line 351 def indexKeys( index ) raise MUES::IndexError, "No such index #{index}" unless self.hasIndex?( index ) @indexes[index.to_s.intern].keys end
Given the indexValuePairs Hash, which contains index => lookup values pairs, return objects which match the equality natural join of the pairs.
# File lib/mues/os-extensions/dbibackend.rb, line 221 def lookup( indexValuePairs ) checkOpened() objs = [] indexValuePairs.keys.each {|idx| raise MUES::ObjectStoreError, "No such index #{idx.inspect}" unless @indexes.has_key? idx } begin cursors = [] # @env.begin( 0, @db ) {|txn, db| indexValuePairs.each {|idx,vals| self.log.debug { "Looking up values '#{vals.inspect}' for idx '#{idx.inspect}'" } vals.to_a.each {|val| self.log.debug { "Fetching cursor for '#{val}'" } #cursor = txn.associate( @indexes[idx] ).cursor cursor = @indexes[idx].cursor rval = cursor.set( val ) self.log.debug { "Got a cursor with #{cursor.count} values." } cursors << cursor } } self.log.debug {"Preparing to do a join with #{cursors.length} cursors."} @db.join(cursors) {|key,val| self.log.debug {"Adding a '%s' object (%s) for join." % [val.class.name, val.muesid]} # Have to do this despite the source saying not to # use this method because the delegator it returns # doesn't delegate inherited methods... objs << val.to_orig val = nil } #self.log.debug "Closing join transaction..." #txn.close #} rescue => err self.log.error "Transaction failed while fetching values: %s: %s" % [ err.message, err.backtrace.join("\n\t") ] self.log.notice "Attempting recovery" @env.recover {|txn, id| self.log.error "Discarding txn #{id}" txn.discard } end self.log.debug {"Join returned '%d' ids" % objs.length} return objs end
Returns the number of objects stored in the database/
# File lib/mues/os-extensions/dbibackend.rb, line 302 def nitems checkOpened() @db.length end
Returns true if the backend‘s datastore is open.
# File lib/mues/os-extensions/dbibackend.rb, line 296 def open? @open end
Retrieve the objects that have the specified ids from the database and return them.
# File lib/mues/os-extensions/dbibackend.rb, line 163 def retrieve( *ids ) checkOpened() objs = [] begin objs.replace ids.collect {|id| @db[ id ].to_orig} rescue => err raise MUES::ObjectStoreError, "Transaction failed while fetching: #{err.message}", err.backtrace end return objs end
Fetch and return every object stored in the ObjectStore.
# File lib/mues/os-extensions/dbibackend.rb, line 202 def retrieve_all checkOpened() objs = nil begin objs.replace( @db.values.collect {|o| o.to_orig} ) rescue => err raise MUES::ObjectStoreError, "Transaction failed while fetching values: #{err.message}", err.backtrace end return objs end
Retrieve the object/s specified by the given key and value. The specified key may be a Symbol or a String, and must be a valid index.
# File lib/mues/os-extensions/dbibackend.rb, line 183 def retrieve_by_index( key, val ) checkOpened() raise ArgumentError, "Invalid index #{key.inspect}" unless @indexes.has_key?[ key.to_s ] objs = nil begin objs.replace( @indexes[key.to_s.intern].duplicates(val, false) ) rescue => err raise MUES::ObjectStoreError, "Transaction failed while fetching: #{err.message}", err.backtrace end return objs end
Store the specified objects in the database.
# File lib/mues/os-extensions/dbibackend.rb, line 133 def store( *objects ) objects.flatten! checkOpened() checkEachType( objects, MUES::StorableObject ) self.log.debug { "Storing %d objects" % objects.length } begin # Start a transaction and store each object. Txn # auto-commits at the end of the block. self.log.debug { " Beginning transaction..." } # @env.begin( BDB::TXN_COMMIT, @db ) do |txn, db| objects.each {|obj| id = obj.objectStoreId self.log.debug { " Storing object '#{obj.objectStoreId}'..." } @db[ id ] = obj } #end self.log.debug { " Done with transaction." } rescue => err raise MUES::ObjectStoreError, "Transaction failed while storing: #{err.message}", err.backtrace end end