# * George Moschovitis # (c) 2004-2005 Navel, all rights reserved. # $Id: filesys.rb 281 2005-03-10 12:24:14Z gmosx $ require 'fileutils' require 'og/adapter' require 'og/connection' require 'glue/attribute' module Og # The Filesys adapter. This adapter stores Og objectes in # the filesystem. This adapter is a proof of concept and # at the moment severely limited. For extra documentation # see lib/og/adapter.rb class FilesysAdapter < Adapter # Creates the name of the database root dir. def self.dir(database) "#{database}_db" end def create_db(database, user = nil, password = nil) begin FileUtils.mkdir_p(self.class.dir(database)) rescue Logger.error "Cannot create '#{database}'!" end end def drop_db(database, user = nil, password = nil) begin FileUtils.rmdir(self.class.dir(database)) super rescue Logger.error "Cannot drop '#{database}'!" end end def insert_code(klass, db, pre_cb, post_cb) props = props_for_insert(klass) values = props.collect { |p| write_prop(p) }.join(',') sql = "INSERT INTO #{klass::DBTABLE} (#{props.collect {|p| p.name}.join(',')}) VALUES (#{values})" %{ #{pre_cb} conn.store.query("#{sql}").close @oid = conn.store.last_insert_row_id #{post_cb} } end def new_connection(db) return FilesysConnection.new(db) end # A 'table' is emulated by using a directory to store # one file per table row. Each file contains an object # marshaled in YAML format. A special file called # '_sequence' stores the sequence for this 'table'. def create_table(klass, db) class_dir = File.join(self.class.dir(db.config[:database]), klass::DBTABLE) FileUtils.mkdir_p(class_dir) seq_file = File.join(class_dir, 'seq') File.open(seq_file, 'w') { |f| f << '1' } rescue => ex Logger.error "Cannot create directory to store '#{klass}' classes!" end end # The Filesys adapter connection. class FilesysConnection < Connection def initialize(db) super config = db.config begin raise unless File.directory?(FilesysAdapter.dir(config[:database])) rescue => ex if true # ex.to_s =~ /database .* does not exist/i Logger.info "Database '#{config[:database]}' not found!" @db.adapter.create_db(config[:database], config[:user]) retry end raise end end def save(obj) seq = nil class_dir = File.join(FilesysAdapter.dir(@db.config[:database]), obj.class::DBTABLE) File.open(File.join(class_dir, 'seq'), 'r') { |f| seq = f.read.to_i } obj.oid = seq File.open(File.join(class_dir, "#{seq}.yml"), 'w') { |f| f << obj.to_yaml } seq += 1 File.open(File.join(class_dir, 'seq'), 'w') { |f| f << seq } end def load(oid, klass) obj = nil class_dir = File.join(FilesysAdapter.dir(@db.config[:database]), klass::DBTABLE) File.open(File.join(class_dir, "#{oid}.yml"), 'r') { |f| obj = YAML::load(f.read) } return obj end def close Logger.debug "Closed DB connection." if $DBG end end end