# Web::Persistent
# Copyright(c) 2002 MoonWolf <moonwolf@moonwolf.com>
require 'web/persistent/idgen'
require 'web/persistent/serialize'
require 'web/persistent/store'
require 'web/persistent/lock'

module Web
  class Persistent
    def initialize(id=nil, options={})
      @idgen     = options[:idgen]     || Web::Persistent::IDgen::Default
      @iggen_opt = options[:idgen_opt] || {}
      if id
        @persistent_id = id
      else
        @persistent_id = @idgen::unique_id
      end
      
      @serializer     = options[:serializer]     || Web::Persistent::Serialize::Marshal
      @serializer_opt = options[:serializer_opt] || {}
      
      @storeman       = options[:storeman]       || Web::Persistent::Store::GDBM
      @storeman_opt   = options[:storeman_opt]   || {:dir=>'/tmp',:prefix=>'gdbm'}
      @store          = @storeman.new(@persistent_id, @storeman_opt)
      
      @lockman        = options[:lockman]        || Web::Persistent::Lock::Flock
      @lockman_opt    = options[:lockman_opt]    || {:dir=>'/tmp',:prefix=>'lock'}
      @lock           = @lockman.new(@persistent_id, @lockman_opt)
      
      @in_transaction = false
    end

    def close
      @store.close
    end

    def persistent_id
      @persistent_id
    end

    def in_transaction
      raise "not in transaction" unless @in_transaction
    end
    
    def transaction
      raise "nested transaction" if @in_transaction
      @in_transaction = true
      
      @lock.lock
      @store.open
      
      yield
      
      @store.close
      @lock.unlock
      
      @in_transaction = false
    end
    
    
    def [](key)
      in_transaction
      str = @store[key]
      if str
        value = @serializer.restore(str)
      else
        nil
      end
    end

    def []=(key,obj)
      in_transaction
      str = @serializer.dump(obj)
      @store[key] = str
    end
    
    def has_key?(key)
      in_transaction
      @store.has_key?(key)
    end
    
    def delete(key)
      in_transaction
      @store.delete(key)
    end
    
    def keys
      in_transaction
      @store.keys
    end
    
  end # Persistent
end # Web
