<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>lib/strokedb/views/file_view_storage.rb</filename>
    </added>
    <added>
      <filename>lib/strokedb/views/view_storage.rb</filename>
    </added>
    <added>
      <filename>spec/lib/strokedb/document/metaslot_spec.rb</filename>
    </added>
    <added>
      <filename>vendor/rbmodexcl/mrimodexcl.rb</filename>
    </added>
    <added>
      <filename>vendor/rbmodexcl/rbxmodexcl.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -99,7 +99,7 @@ module StrokeDB
       def initialize(document)
         @document = document
         _meta = document[:meta]
-        concat [_meta].flatten.compact.map{|v| v.is_a?(DocumentReferenceValue) ? v.load : v}
+        concat _meta.to_a
       end
 
       def &lt;&lt;(meta)
@@ -204,6 +204,7 @@ module StrokeDB
     # If slot was not found, it will return &lt;tt&gt;nil&lt;/tt&gt;
     #
     def [](slotname)
+      slotname = slotname.document.uuid if (slotname.is_a?(Meta) &amp;&amp; slotname.is_a?(Module)) || (slotname == Meta)
       @slots[slotname.to_s].value rescue nil
     end
 
@@ -213,6 +214,7 @@ module StrokeDB
     #   document[:slot_1] = &quot;some value&quot;
     #
     def []=(slotname, value)
+      slotname = slotname.document.uuid  if (slotname.is_a?(Meta) &amp;&amp; slotname.is_a?(Module)) || (slotname == Meta)
       slotname = slotname.to_s
 
       (@slots[slotname] ||= Slot.new(self, slotname)).value = value
@@ -283,7 +285,11 @@ module StrokeDB
           if %w(version previous_version).member?(k) &amp;&amp; v = self[k]
             s &lt;&lt; &quot;#{k}: #{v[0,4]}..., &quot;
           else
-            s &lt;&lt; &quot;#{k}: #{self[k].inspect}, &quot;
+            if k.match(/^#{UUID_RE}$/)
+              s &lt;&lt; &quot;[#{store.find(k).name}]: #{self[k].inspect}, &quot; rescue s &lt;&lt; &quot;#{k}: #{self[k].inspect}, &quot;
+            else
+              s &lt;&lt; &quot;#{k}: #{self[k].inspect}, &quot;
+            end
           end
         end
 
@@ -324,7 +330,7 @@ module StrokeDB
         raw_slots[k.to_s] = v.to_raw
       end
 
-      raw_slots
+      raw_slots.to_raw
     end
 
     def to_optimized_raw #:nodoc:
@@ -334,8 +340,8 @@ module StrokeDB
     #
     # Creates a document from a serialized representation
     #
-    def self.from_raw(store, raw_slots, opts = {}) #:nodoc:
-      doc = new(store, raw_slots, true)
+    def self.from_raw(store, raw_slots, opts = {}, &amp;block) #:nodoc:
+      doc = new(store, raw_slots, true, &amp;block)
 
       collect_meta_modules(store, raw_slots['meta']).each do |meta_module|
         unless doc.is_a? meta_module
@@ -662,7 +668,6 @@ module StrokeDB
     # initialize slots from a raw representation
     def initialize_raw_slots(slots) #:nodoc:
       @slots = {}
-
       slots.each do |name,value|
         s = Slot.new(self, name)
         s.raw_value = value</diff>
      <filename>lib/strokedb/document.rb</filename>
    </modified>
    <modified>
      <diff>@@ -100,9 +100,9 @@ module StrokeDB
         #   meta = _t.join('::') 
         # end
         
-        view = View.define!(&quot;#{name.modulize.empty? ? Module.nsurl : name.modulize.constantize.nsurl}##{name.demodulize.tableize.singularize}_has_many_#{slotname}&quot;,
-                            { :reference_slotname =&gt; reference_slotname, :through =&gt; through, :expected_meta =&gt; meta, :expected_nsurl =&gt; nsurl, :extend_with =&gt; extend_with, 
-                              :conditions =&gt; conditions, :sort_by =&gt; sort_by, :reverse =&gt; reverse }, &amp;AssociationViewImplementation)
+        view = View.named(&quot;#{name.modulize.empty? ? Module.nsurl : name.modulize.constantize.nsurl}##{name.demodulize.tableize.singularize}_has_many_#{slotname}&quot;,
+                                { :reference_slotname =&gt; reference_slotname, :through =&gt; through, :expected_meta =&gt; meta, :expected_nsurl =&gt; nsurl, :extend_with =&gt; extend_with, 
+                                :conditions =&gt; conditions, :sort_by =&gt; sort_by, :reverse =&gt; reverse }, &amp;AssociationViewImplementation)
         
         @args.last.reverse_merge!({&quot;has_many_#{slotname}&quot; =&gt; view})
         define_method(slotname) do </diff>
      <filename>lib/strokedb/document/dsl/associations.rb</filename>
    </modified>
    <modified>
      <diff>@@ -91,8 +91,10 @@ module StrokeDB
     end
 
     def implements(another_meta)
-      values = @args.select{|a| a.is_a?(Hash) }.first
+      values = @args.find{|a| a.is_a?(Hash) }
       values.merge!(another_meta.document.to_raw.delete_if {|k,v| ['name','uuid','version','previous_version','meta'].member?(k) })
+      values[:implements_metas] ||= []
+      values[:implements_metas] &lt;&lt; another_meta.document
       include(another_meta)
       self
     end
@@ -124,10 +126,10 @@ module StrokeDB
     def named(*args,&amp;block)
       args.unshift StrokeDB.default_store unless args.first.is_a?(StrokeDB::Store)
       args &lt;&lt; {} unless args.last.is_a?(Hash)
-      raise InvalidArgumentError, &quot;you should specify name&quot; unless args[1].is_a?(String)
+      raise ArgumentError, &quot;you should specify name&quot; unless args[1].is_a?(String)
       name = args[1]
       uuid = ::StrokeDB::Util.sha1_uuid(&quot;#{document.uuid}:#{name}&quot;)
-      unless doc = find(args[0],uuid)
+      unless doc = find(args[0],uuid,&amp;block)
         doc = create!(args[0],args.last.reverse_merge(:uuid =&gt; uuid),&amp;block)
       else
         doc.update_slots!(args.last)
@@ -192,7 +194,7 @@ module StrokeDB
     #   all_my_joes  = User.find(my_store, :name =&gt; &quot;joe&quot;)
     #   oh_my        = User.find(my_store, &quot;1e3d02cc-0769-4bd8-9113-e033b246b013&quot;)
     #
-    def find(*args)
+    def find(*args, &amp;block)
       if args.empty? || !args.first.respond_to?(:search)
         raise NoDefaultStoreError unless StrokeDB.default_store
         
@@ -209,8 +211,7 @@ module StrokeDB
       case args[1]
       when String
         raise ArgumentError, &quot;Invalid UUID&quot; unless args[1].match(UUID_RE)
-
-        store.search(opt.merge({ :uuid =&gt; args[1] })).first
+        store.find(args[1], &amp;block)
       when Hash
         store.search opt.merge(args[1])
       when nil</diff>
      <filename>lib/strokedb/document/meta.rb</filename>
    </modified>
    <modified>
      <diff>@@ -11,6 +11,7 @@ module StrokeDB
       super(*args)
       @modification_callback.call if @modification_callback
     end
+    
   end
 
   class ArraySlotValue &lt; LazyMappingArray
@@ -70,6 +71,7 @@ module StrokeDB
       &quot;#&lt;DocRef #{self[0,5]}..&gt;&quot;
     end
     alias :to_raw :str
+    alias :to_s :str
 
     def ==(v)
       case v
@@ -160,7 +162,7 @@ module StrokeDB
     def decode_value(v)
       case v
       when VERSIONREF
-        DocumentReferenceValue.new(v, doc)
+        DocumentReferenceValue.new(v.to_s, doc)
       when DUMP_PREFIX_RE
         StrokeDB::deserialize(v[7, v.length-7])
       when Array</diff>
      <filename>lib/strokedb/document/slot.rb</filename>
    </modified>
    <modified>
      <diff>@@ -51,7 +51,7 @@ module StrokeDB
       # Returns &lt;tt&gt;nil&lt;/tt&gt; if there is no previous version
       #
       def previous
-        self[document.previous_version]
+        document.previous_version ? self[document.previous_version] : nil
       end
 
       #</diff>
      <filename>lib/strokedb/document/versions.rb</filename>
    </modified>
    <modified>
      <diff>@@ -16,8 +16,8 @@ module StrokeDB
       raise &quot;Missing chunk storage&quot; unless @storage
     end
 
-    def find(uuid, version=nil, opts = {})
-      @storage.find(uuid,version,opts.merge(:store =&gt; self))
+    def find(uuid, version=nil, opts = {}, &amp;block)
+      @storage.find(uuid,version,opts.merge(:store =&gt; self),&amp;block)
     end
 
     def search(*args)
@@ -52,12 +52,12 @@ module StrokeDB
         @index_store.save!
       end
     end  
-    
+
     def save_as_head!(doc)
       @storage.save_as_head!(doc,timestamp)
       update_views!(doc)
     end
-    
+
 
 
     def each(options = {},&amp;block)
@@ -87,7 +87,10 @@ module StrokeDB
     def autosync!
       @autosync_mutex ||= Mutex.new
       @autosync = nil if @autosync &amp;&amp; !@autosync.status
-      at_exit { stop_autosync! }
+      @stop_autosync = false
+      at_exit do
+         stop_autosync! unless @stop_autosync
+       end
       @autosync ||= Thread.new do 
         until @stop_autosync
           @autosync_mutex.synchronize { storage.sync_chained_storages! }
@@ -95,10 +98,19 @@ module StrokeDB
         end
       end
     end
+    
+    def autosync?
+      @autosync &amp;&amp; !@autosync.status
+    end
 
     def stop_autosync!
       if @autosync_mutex
-        @autosync_mutex.synchronize { @stop_autosync = true; storage.sync_chained_storages! }
+        @autosync_mutex.synchronize do
+          unless @stop_autosync
+            @stop_autosync = true
+            storage.sync_chained_storages! 
+          end
+        end
       end
     end
 </diff>
      <filename>lib/strokedb/store.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,6 @@
 module StrokeDB
+  RAW_HEAD_VERSION_UUID         = Util.sha1_uuid(&quot;strokedb-internal:head-version&quot;).to_raw_uuid
+
   class FileStorage &lt; Storage
 
     def initialize(options = {})
@@ -7,16 +9,16 @@ module StrokeDB
     end
 
     def save_as_head!(document, timestamp)
-      write(document.uuid, document, timestamp)
+      save!(document,timestamp, :head =&gt; true)
     end      
 
-    def find(uuid, version=nil, opts = {})
+    def find(uuid, version=nil, opts = {}, &amp;block)
       uuid_version = uuid + (version ? &quot;.#{version}&quot; : &quot;&quot;)
-      key = uuid.to_raw_uuid + (version ? version.to_raw_uuid : NIL_UUID.to_raw_uuid)
-      if (ptr = @uindex.find(key)) &amp;&amp; (ptr != &quot;\x00&quot; * 20) # no way ptr will be zero
-        raw_doc = StrokeDB::deserialize(read_at_ptr(ptr))[0]
+      key = uuid.to_raw_uuid + (version ? version.to_raw_uuid : RAW_HEAD_VERSION_UUID)
+      if (ptr = @uindex.find(key)) &amp;&amp; (ptr[0,20] != &quot;\x00&quot; * 20) # no way ptr will be zero
+        raw_doc = StrokeDB::deserialize(read_at_ptr(ptr[0,20]))
         unless opts[:no_instantiation]
-          doc = Document.from_raw(opts[:store], raw_doc.freeze) # FIXME: there should be a better source for store (probably)
+          doc = Document.from_raw(opts[:store], raw_doc.freeze, &amp;block) # FIXME: there should be a better source for store (probably)
           doc.extend(VersionedDocument) if version
           doc
         else
@@ -26,8 +28,10 @@ module StrokeDB
     end
 
     def include?(uuid,version=nil)
-      !!find(uuid,version,:no_instantiation =&gt; true)
+      key = uuid.to_raw_uuid + (version ? version.to_raw_uuid : RAW_HEAD_VERSION_UUID)
+      !@uindex.find(key).nil?
     end
+    
     # using #include? to match with Array, but #contains sounds much nicer
     alias_method :contains?, :include?
 
@@ -40,20 +44,23 @@ module StrokeDB
     def each(options = {})
       after = options[:after_timestamp]
       include_versions = options[:include_versions]
-      @container.each do |key, value|
-        next if after &amp;&amp; (value[1] &lt;= after)
-        if uuid_match = key.match(/^#{UUID_RE}$/) || (include_versions &amp;&amp; uuid_match = key.match(/#{UUID_RE}./) )
-          yield Document.from_raw(options[:store],value[0])
+      @uindex.each do |key, value|
+        timestamp = StrokeDB.deserialize(read_at_ptr(value[20,20]))
+        next if after &amp;&amp; (timestamp &lt;= after)
+        if key[16,16] == RAW_HEAD_VERSION_UUID || include_versions
+          yield Document.from_raw(options[:store],StrokeDB.deserialize(read_at_ptr(value[0,20])))
         end
       end
     end
 
     def perform_save!(document, timestamp, options = {})
-      position = @archive.insert(StrokeDB::serialize([document,timestamp.counter]))
+      ts_position = @archive.insert(StrokeDB::serialize(timestamp.counter))
+      position = @archive.insert(StrokeDB::serialize(document))
+      ts_ptr = DistributedPointer.pack(@archive.raw_uuid,ts_position)
       ptr = DistributedPointer.pack(@archive.raw_uuid,position)
       uuid = document.raw_uuid
-      @uindex.insert(uuid + RAW_NIL_UUID, ptr) if options[:head] || !document.is_a?(VersionedDocument)
-      @uindex.insert(uuid + document.version.to_raw_uuid, ptr) unless options[:head]
+      @uindex.insert(uuid + RAW_HEAD_VERSION_UUID, ptr + ts_ptr) if options[:head] || !document.is_a?(VersionedDocument)
+      @uindex.insert(uuid + document.version.to_raw_uuid, ptr + ts_ptr) unless options[:head]
     rescue ArchiveVolume::VolumeCapacityExceeded	 
       create_new_archive!
     end</diff>
      <filename>lib/strokedb/stores/file_storage.rb</filename>
    </modified>
    <modified>
      <diff>@@ -10,13 +10,13 @@ module StrokeDB
       save!(document,timestamp, :head =&gt; true)
 		end      
     
-    def find(uuid, version=nil, opts = {})
+    def find(uuid, version=nil, opts = {},&amp;block)
       uuid_version = uuid + (version ? &quot;.#{version}&quot; : &quot;&quot;)
       unless raw_doc = read(uuid_version)
-        authoritative_source.find(uuid,version,opts) if authoritative_source
+        authoritative_source.find(uuid,version,opts,&amp;block) if authoritative_source
       else
         unless opts[:no_instantiation]
-          doc = Document.from_raw(opts[:store], raw_doc.freeze) # FIXME: there should be a better source for store (probably)
+          doc = Document.from_raw(opts[:store], raw_doc.freeze, &amp;block) # FIXME: there should be a better source for store (probably)
           doc.extend(VersionedDocument) if version
           doc
         else</diff>
      <filename>lib/strokedb/stores/memory_storage.rb</filename>
    </modified>
    <modified>
      <diff>@@ -135,6 +135,10 @@ module StrokeDB
     def to_a
        Array.new(map{|v| v})
     end
+    
+    def ==(arr)
+      to_a == arr
+    end
 
     def class
       Array</diff>
      <filename>lib/strokedb/util/lazy_mapping_array.rb</filename>
    </modified>
    <modified>
      <diff>@@ -7,6 +7,18 @@ module StrokeDB
       end
     end
   end
+
+  class ::Hash
+    def to_raw
+      raw_hash = {}
+      map do |k,v|
+        _k = k.respond_to?(:to_raw) ? k.to_raw : k
+        _v = v.respond_to?(:to_raw) ? v.to_raw : v
+        raw_hash[_k] = _v
+      end
+      raw_hash
+    end
+  end
   
   module JsonSerializationMethod
     def serialize(x)</diff>
      <filename>lib/strokedb/util/serialization.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,7 @@
 require 'views/store_ext'
 require 'views/default_key_encoder'
 require 'views/raw_data_meta'
+require 'views/view_storage'
 require 'views/memory_view_storage'
+require 'views/file_view_storage'
 require 'views/view'</diff>
      <filename>lib/strokedb/views.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,62 +1,13 @@
 module StrokeDB
-  class MemoryViewStorage
-    attr_reader :storage, :options, :exists
+  class MemoryViewStorage &lt; ViewStorage
     
     def initialize(options = {})
-      # TODO: find out whether the view indexfile exists and read
-      #       its options
       @list = SimpleSkiplist.new
     end
     
-    def set_options(options)
-      # if exists? &amp;&amp; self.options != options
-      #   raise StandardError, &quot;Couldn't change options for an existing storage!&quot;
-      # end
-      
-      @options = options
-      
-    end
-        
-    # 
-    #
-    def find(start_key, end_key, limit, offset, reverse, with_keys)
-      @list.search(start_key, end_key, limit, offset, reverse, with_keys)
-    end
-        
-    # 
-    #
-    def replace(old_pairs, new_pairs)
-      old_pairs.each do |pair|
-        key, value = pair
-        @list.insert(key,nil) if @list.find(key)
-      end
-      insert(new_pairs)
-    end
-    
-    #
-    #
-    def insert(new_pairs)
-      new_pairs.each do |pair|
-        key, value = pair
-        @list.insert(key, value)
-      end
-    end
-    
-    #
-    #
-    def exists?
-      true
-    end
-    
-    #
-    #
     def clear!
       @list = SimpleSkiplist.new
     end
     
-    def empty?
-      @list.empty?
-    end
-    
   end
 end</diff>
      <filename>lib/strokedb/views/memory_view_storage.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,7 @@
 module StrokeDB
   class Store
-
+    
+    
     # Tells a store to update a view on document save.
     #
     def register_view(v, metas = nil) #:nodoc:
@@ -52,5 +53,11 @@ module StrokeDB
         # meta_name =&gt; [...].to_set
       }
     end
+    
+
+    def view_storage(uuid)
+      @view_storages ||= {}
+      @view_storages[uuid] ||= FileViewStorage.new(:path =&gt; File.join(@options['path'],&quot;views/#{uuid}&quot;))
+    end
   end
 end</diff>
      <filename>lib/strokedb/views/store_ext.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,5 @@
 module StrokeDB
   VIEW_CACHE = {}
-  VIEW_STORAGES = {}
   
   View = Meta.new do 
     
@@ -33,11 +32,16 @@ module StrokeDB
       if initialization_block = viewdoc.instance_variable_get(:@initialization_block) || initialization_block = VIEW_CACHE[viewdoc.uuid]
         initialization_block.call(viewdoc)
       end
-      viewdoc.store.register_view(viewdoc, viewdoc['only'])
+      # name = viewdoc['name']
+      # raise ArgumentError, &quot;View name must be specified!&quot; unless name
+      nsurl = viewdoc['nsurl'] ||= name.modulize.empty? ? Module.nsurl : name.modulize.constantize.nsurl # FIXME: it is not nice (and the same shit is in meta.rb)
+      # viewdoc.instance_variable_set(:@uuid, ::StrokeDB::Util.sha1_uuid(&quot;view:#{nsurl}##{name}&quot;))
+      
     end
     
     after_save do |viewdoc|
       VIEW_CACHE[viewdoc.uuid] = viewdoc.instance_variable_get(:@initialization_block)
+      viewdoc.store.register_view(viewdoc, viewdoc['only'])
     end
     
     DEFAULT_FIND_OPTIONS = {
@@ -236,9 +240,9 @@ module StrokeDB
     private :map_with_encoding
     
     def storage
-      # @storage ||= store.view_storages[self.uuid]
-      VIEW_STORAGES[uuid] ||= MemoryViewStorage.new
+      @storage ||= store.view_storage(self.uuid)
     end
+    
     private :storage
 
     # These are defaults (to be overriden in View.new{|v| ... })
@@ -275,58 +279,6 @@ module StrokeDB
     end
   end
   
-  # Note: we don't simply do Views = View to avoid &quot;Views&quot; in a meta name.
-  # This class is for Views[&quot;name&quot;] only.
-  class Views
-    def self.[](view_name)
-      View[view_name]
-    end
-  end
-  
-  class &lt;&lt; View
-    def [](*args) # FIXME: it is not nice
-      store = args.first.is_a?(Store) ? args.shift : StrokeDB.default_store
-      name = args[0]
-      nsurl = args[1] || (name.modulize.empty? ? Module.nsurl : name.modulize.constantize.nsurl)
-      uuid = ::StrokeDB::Util.sha1_uuid(&quot;view:#{nsurl}##{name}&quot;) 
-      store.find(uuid)
-    end
-
-    alias :original_new :new
-    # Define a view. 
-    #
-    # Examples
-    #   View.new(&quot;view_name&quot;, :option =&gt; &quot;value&quot;) do |viewdoc| ... end
-    #   View.new(:name =&gt; &quot;view_name&quot;, :option =&gt; &quot;value&quot;) do |viewdoc| ... end
-    #   View.new(store, &quot;view_name&quot;, :option =&gt; &quot;value&quot;) do |viewdoc| ... end
-    #   View.new(store, :name =&gt; &quot;view_name&quot;, :option =&gt; &quot;value&quot;) do |viewdoc| ... end
-    #
-    def new(*args, &amp;block)
-      
-      store, name, options = extract(Store, String, Hash, args)
-      
-      store ||= StrokeDB.default_store
-      options = options &amp;&amp; options.stringify_keys || {}
-      name ||= options['name']
-      
-      raise ArgumentError, &quot;View name must be specified!&quot; unless name
-      
-      nsurl = options['nsurl'] ||= name.modulize.empty? ? Module.nsurl : name.modulize.constantize.nsurl # FIXME: it is not nice (and the same shit is in meta.rb)
-      
-      options['uuid'] = ::StrokeDB::Util.sha1_uuid(&quot;view:#{nsurl}##{name}&quot;) 
-      
-      unless v = find(options['uuid'])
-        v = original_new(store, options, &amp;block)
-      end
-      v
-    end
-        
-    alias :define :new
-    alias :define! :create!
-    
-  end
-  
-
   class InvalidViewError &lt; StandardError ; end
   
 end</diff>
      <filename>lib/strokedb/views/view.rb</filename>
    </modified>
    <modified>
      <diff>@@ -112,6 +112,10 @@ module StrokeDB
       @list.search(*args)
     end
     
+    def each(*args, &amp;block)
+      @list.each(*args, &amp;block)
+    end
+    
     def find(key)
       @list.find(key)
     end
@@ -274,7 +278,7 @@ module StrokeDB
     end
     
     def info(m)
-      STDOUT.puts &quot;SkiplistVolume#info: #{m}&quot;
+      DEBUG { STDOUT.puts &quot;SkiplistVolume#info: #{m}&quot; }
     end
     
     def error(m)</diff>
      <filename>lib/strokedb/volumes/skiplist_volume.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,3 +1,4 @@
+bench.html
 bin/strokedb
 examples/movies.rb
 examples/movies2.rb
@@ -14,7 +15,9 @@ lib/strokedb/console.rb
 lib/strokedb/core_ext/blank.rb
 lib/strokedb/core_ext/enumerable.rb
 lib/strokedb/core_ext/fixnum.rb
+lib/strokedb/core_ext/float.rb
 lib/strokedb/core_ext/hash.rb
+lib/strokedb/core_ext/infinity.rb
 lib/strokedb/core_ext/kernel.rb
 lib/strokedb/core_ext/object.rb
 lib/strokedb/core_ext/string.rb
@@ -26,18 +29,21 @@ lib/strokedb/data_structures/point_query.rb
 lib/strokedb/data_structures/simple_skiplist.rb
 lib/strokedb/data_structures/skiplist.rb
 lib/strokedb/data_structures.rb
-lib/strokedb/document/associations.rb
 lib/strokedb/document/callback.rb
-lib/strokedb/document/coercions.rb
 lib/strokedb/document/delete.rb
+lib/strokedb/document/dsl/associations.rb
+lib/strokedb/document/dsl/coercions.rb
+lib/strokedb/document/dsl/meta_dsl.rb
+lib/strokedb/document/dsl/validations.rb
+lib/strokedb/document/dsl/virtualize.rb
+lib/strokedb/document/dsl.rb
 lib/strokedb/document/meta.rb
 lib/strokedb/document/slot.rb
 lib/strokedb/document/util.rb
-lib/strokedb/document/validations.rb
 lib/strokedb/document/versions.rb
-lib/strokedb/document/virtualize.rb
 lib/strokedb/document.rb
 lib/strokedb/index.rb
+lib/strokedb/nsurl.rb
 lib/strokedb/store.rb
 lib/strokedb/stores/chainable_storage.rb
 lib/strokedb/stores/file_storage.rb
@@ -55,6 +61,7 @@ lib/strokedb/sync/lamport_timestamp.rb
 lib/strokedb/sync/store_sync.rb
 lib/strokedb/sync.rb
 lib/strokedb/transaction.rb
+lib/strokedb/util/attach_dsl.rb
 lib/strokedb/util/blankslate.rb
 lib/strokedb/util/class_optimization.rb
 lib/strokedb/util/inflect.rb
@@ -70,8 +77,8 @@ lib/strokedb/view.rb
 lib/strokedb/volumes/archive_volume.rb
 lib/strokedb/volumes/block_volume.rb
 lib/strokedb/volumes/distributed_pointer.rb
+lib/strokedb/volumes/fixed_length_skiplist_volume.rb
 lib/strokedb/volumes/map_volume.rb
-lib/strokedb/volumes/skiplist_volume.rb
 lib/strokedb/volumes.rb
 lib/strokedb.rb
 README
@@ -82,6 +89,9 @@ spec/integration/spec_helper.rb
 spec/lib/spec_helper.rb
 spec/lib/strokedb/config_spec.rb
 spec/lib/strokedb/core_ext/blank_spec.rb
+spec/lib/strokedb/core_ext/extract_spec.rb
+spec/lib/strokedb/core_ext/float_spec.rb
+spec/lib/strokedb/core_ext/infinity_spec.rb
 spec/lib/strokedb/core_ext/spec_helper.rb
 spec/lib/strokedb/core_ext/string_spec.rb
 spec/lib/strokedb/core_ext/symbol_spec.rb
@@ -91,14 +101,17 @@ spec/lib/strokedb/data_structures/simple_skiplist_spec.rb
 spec/lib/strokedb/data_structures/skiplist_spec.rb
 spec/lib/strokedb/data_structures/spec_helper.rb
 spec/lib/strokedb/document/associations_spec.rb
+spec/lib/strokedb/document/callbacks_spec.rb
 spec/lib/strokedb/document/coercions_spec.rb
 spec/lib/strokedb/document/document_spec.rb
 spec/lib/strokedb/document/meta_meta_spec.rb
 spec/lib/strokedb/document/meta_spec.rb
+spec/lib/strokedb/document/metaslot_spec.rb
 spec/lib/strokedb/document/slot_spec.rb
 spec/lib/strokedb/document/spec_helper.rb
 spec/lib/strokedb/document/validations_spec.rb
 spec/lib/strokedb/document/virtualize_spec.rb
+spec/lib/strokedb/nsurl_spec.rb
 spec/lib/strokedb/spec_helper.rb
 spec/lib/strokedb/stores/chained_storages_spec.rb
 spec/lib/strokedb/stores/spec_helper.rb
@@ -116,6 +129,7 @@ spec/lib/strokedb/sync/stroke_diff/hash_spec.rb
 spec/lib/strokedb/sync/stroke_diff/scalar_spec.rb
 spec/lib/strokedb/sync/stroke_diff/spec_helper.rb
 spec/lib/strokedb/sync/stroke_diff/string_spec.rb
+spec/lib/strokedb/util/attach_dsl_spec.rb
 spec/lib/strokedb/util/inflect_spec.rb
 spec/lib/strokedb/util/lazy_array_spec.rb
 spec/lib/strokedb/util/lazy_mapping_array_spec.rb
@@ -135,6 +149,17 @@ spec/regression/spec_helper.rb
 spec/regression/sync_spec.rb
 spec/spec.opts
 spec/spec_helper.rb
+spec/temp/storages/database-sync/config
+spec/temp/storages/database-sync/file/bd/f6/bdf675e5-8a7b-494e-97f2-f74a14ccd95d.av
+spec/temp/storages/database-sync/file/LAST
+spec/temp/storages/database-sync/file/uindex.wal
+spec/temp/storages/database-sync/inverted_list_file/INVERTED_INDEX
+spec/temp/storages/database-sync/TIMESTAMP
+spec/temp/storages/database-sync/UUID
+spec/temp/storages/inverted_list_storage/INVERTED_INDEX
+spec/temp/storages/TIMESTAMP
+spec/temp/storages/UUID
+strokedb.gemspec
 task/benchmark.task
 task/ditz.task
 task/echoe.rb
@@ -142,4 +167,9 @@ task/rcov.task
 task/rdoc.task
 task/rspec.task
 vendor/java_inline.rb
+vendor/rbmodexcl/mrimodexcl.rb
+vendor/rbmodexcl/rbmodexcl.rb
+vendor/rbmodexcl/rbxmodexcl.rb
+vendor/rbmodexcl/spec/unextend_spec.rb
+vendor/rbmodexcl/spec/uninclude_spec.rb
 meta/MANIFEST</diff>
      <filename>meta/MANIFEST</filename>
    </modified>
    <modified>
      <diff>@@ -67,9 +67,7 @@ describe &quot;Database search&quot; do
     oleg[:name] = 'Oleganza'
     oleg.save!
     results = @index.find(:name =&gt; 'Oleg')
-    pending(&quot;#31 changed this behavior somehow, but we anyway going to have new search capabilities with new-views, so I will not care much&quot;) do
-      results.should be_empty
-    end
+    results.should be_empty
     results = @index.find(:name =&gt; 'Oleganza')
     results[0].uuid.should == oleg.uuid
   end</diff>
      <filename>spec/integration/search_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -301,6 +301,10 @@ describe &quot;ImplementsSomeName with implements SomeName meta&quot; do
     ImplementsSomeName.name.should == &quot;ImplementsSomeName&quot;
   end
   
+  it &quot;should reference implemented meta&quot; do
+    ImplementsSomeName.document.implements_metas.should == [SomeName.document]
+  end
+  
   
 end
 
@@ -362,6 +366,9 @@ describe &quot;ImplementsSomeName with multiple implements&quot; do
     ImplementsSomeName.name.should == &quot;ImplementsSomeName&quot;
   end
   
+  it &quot;should reference implemented metas&quot; do
+    ImplementsSomeName.document.implements_metas.to_set.should == [SomeName.document,SomeName1.document].to_set
+  end
   
 end
 </diff>
      <filename>spec/lib/strokedb/document/meta_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -84,7 +84,7 @@ describe &quot;Non-empty store&quot; do
   end
 
   it &quot;should report versioned document that does not exist as such&quot; do
-    @store.include?(@documents.first.uuid,'ouch, there is no way such version could be generated').should == false
+    @store.include?(@documents.first.uuid,StrokeDB::Util.random_uuid).should == false
   end
 
   it &quot;should report document that does not exist as such&quot; do
@@ -102,7 +102,7 @@ describe &quot;Non-empty store&quot; do
   end
 
   it &quot;should not find a versioned document with version that does not exist&quot; do
-    @store.find(@documents.first.uuid,'absolutely absurd version').should be_nil
+    @store.find(@documents.first.uuid,StrokeDB::Util.random_uuid).should be_nil
   end
 
 </diff>
      <filename>spec/lib/strokedb/stores/store_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -18,7 +18,7 @@ describe &quot;LazyMappingArray instance&quot; do
   end
 end
 
-describe &quot;LazyMappingArray instance with block specified&quot; do
+describe &quot;LazyMappingArray instance with map/unmap specified&quot; do
   before(:each) do
     @original = [1,2,3,[1],[2]]
     @mapper = proc {|arg| arg.to_s }
@@ -167,5 +167,8 @@ describe &quot;LazyMappingArray instance with block specified&quot; do
     @array.should_not include(&quot;10&quot;)
   end
 
+  it &quot;should be == to similar non-lazy array&quot; do
+    @array.should == @original.map{|v| @mapper.call(v)}
+  end
+  
 end
-</diff>
      <filename>spec/lib/strokedb/util/lazy_mapping_array_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -8,7 +8,7 @@ describe View, &quot;without a name&quot; do
   
   it &quot;could not be initialized&quot; do
     lambda do 
-      @post_comments = View.define!
+      @post_comments = View.named()
     end.should raise_error(ArgumentError)
   end
   
@@ -20,14 +20,15 @@ describe View, &quot;without #map method defined&quot; do
   end
   
   it &quot;should raise exception when view is created&quot; do
+    pending(&quot;not sure we need it&quot;)
     lambda { 
-       View.define!(:name =&gt; &quot;post_comments_invalid&quot;)
+       View.named(&quot;post_comments_invalid&quot;)
     }.should raise_error(InvalidViewError)
   end
   
   it &quot;should raise exception when #map is used&quot; do
     Comment = Meta.new
-    @post_comments = View.define!(:name =&gt; &quot;post_comments_invalid&quot;, :only =&gt; [&quot;comment&quot;])
+    @post_comments = View.named(&quot;post_comments_invalid&quot;, :only =&gt; [&quot;comment&quot;])
     c = Comment.new :text =&gt; &quot;hello&quot;
     lambda { @post_comments.map(c.uuid, c) }.should raise_error(InvalidViewError)
   end
@@ -38,7 +39,7 @@ describe &quot;'Has many comments' view&quot; do
   
   before(:all) do
     setup_default_store
-    @view = View.define!(&quot;post_comments&quot;) do |view|
+    @view = View.named(&quot;post_comments&quot;) do |view|
       def view.map(uuid, doc)
         doc['type'] =~ /comment/ ? [[[doc.parent, doc.created_at], doc]] : nil
       end
@@ -127,11 +128,17 @@ describe View, &quot;with :only option&quot; do
       Comment          = Meta.new 
     end
     
-    @generic   = View.new(&quot;generic&quot;, &amp;block)
-    @comments  = View.new(&quot;comments&quot;, :only =&gt; [&quot;Comment&quot;], &amp;block)
-    @c_and_a   = View.new(&quot;comments_and_articles&quot;, :only =&gt; [&quot;Comment&quot;, &quot;Article&quot;], &amp;block)
-    @sponsored = View.new(&quot;sponsored&quot;, :only =&gt; [&quot;SponsoredArticle&quot;], &amp;block) 
+    @generic   = View.named(&quot;generic&quot;, &amp;block)
+    @comments  = View.named(&quot;comments&quot;, :only =&gt; [&quot;Comment&quot;], &amp;block)
+    @c_and_a   = View.named(&quot;comments_and_articles&quot;, :only =&gt; [&quot;Comment&quot;, &quot;Article&quot;], &amp;block)
+    @sponsored = View.named(&quot;sponsored&quot;, :only =&gt; [&quot;SponsoredArticle&quot;], &amp;block) 
   end
+
+  after(:each) do
+    StrokeDB.send(:remove_const, :VIEW_CACHE) if defined?(StrokeDB::VIEW_CACHE)
+    StrokeDB::VIEW_CACHE = {}
+  end
+  
   it &quot;should update articles only&quot; do
     a = (A::Article + A::SponsoredArticle).create!(:title =&gt; &quot;This is a sponsored article&quot;)    
     @generic.should      be_updated
@@ -153,7 +160,7 @@ describe View, &quot;with block defined and saved&quot; do
   
   before(:each) do
     setup_default_store
-    @view = View.define!(&quot;SomeView&quot;) do |view|
+    @view = View.named(&quot;SomeView&quot;) do |view|
       def view.map(uuid, doc)
         [[doc,doc]]
       end
@@ -171,9 +178,29 @@ describe View, &quot;with block defined and saved&quot; do
     @view.send(:storage).object_id.should == storage_id
   end
   
-  it &quot;should be findable with #[] syntax&quot; do
-    View[&quot;SomeView&quot;].should == @view
-    View[StrokeDB.default_store, &quot;SomeView&quot;].should == @view
+  it &quot;should be findable with #named syntax&quot; do
+    View.named(&quot;SomeView&quot;).should == @view
+  end
+
+  it &quot;should set block for found-again view if it is supplied&quot; do
+    @view = View.named(&quot;SomeView&quot;) do |view|
+      def view.map(uuid, doc)
+        [[doc,doc]]
+      end
+    end
+    lambda { @view.map(1,2).should == [[1,2]]}.should_not raise_error(InvalidViewError)
+  end
+  
+  it &quot;should set block for found-again view if it is supplied even if it was not cached&quot; do
+    StrokeDB.send(:remove_const, :VIEW_CACHE) if defined?(StrokeDB::VIEW_CACHE)
+    StrokeDB::VIEW_CACHE = {}
+    
+    @view = View.named(&quot;SomeView&quot;) do |view|
+      def view.map(uuid, doc)
+        [[doc,doc]]
+      end
+    end
+    lambda { @view.map(1,2).should == [[1,2]]}.should_not raise_error(InvalidViewError)
   end
   
 end
@@ -183,15 +210,14 @@ describe View, &quot;with nsurl and block defined and saved&quot; do
   
   before(:each) do
     setup_default_store
-    @view = View.define!(&quot;SomeView&quot;, :nsurl =&gt; &quot;http://strokedb.com/&quot;) do |view|
+    @view = View.named(&quot;SomeView&quot;, :nsurl =&gt; &quot;http://strokedb.com/&quot;) do |view|
       def view.map(uuid, doc)
         [[doc,doc]]
       end
     end
   end
-  it &quot;should be findable with #[] syntax&quot; do
-    View[&quot;SomeView&quot;, &quot;http://strokedb.com/&quot;].should == @view
-    View[StrokeDB.default_store, &quot;SomeView&quot;, &quot;http://strokedb.com/&quot;].should == @view
+  it &quot;should be findable with #named syntax&quot; do
+    View.named(&quot;SomeView&quot;).should == @view
   end
   
 end
@@ -201,7 +227,7 @@ describe &quot;View#traverse_key &quot; do
   
   before(:each) do
     setup_default_store
-    @v = View.new(&quot;a&quot;) do |view|
+    @v = View.named(&quot;a&quot;) do |view|
       def view.map(*args); end
     end
   end</diff>
      <filename>spec/lib/strokedb/views/view_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -11,11 +11,17 @@ def setup_default_store(store=nil)
     StrokeDB.stub!(:default_store).and_return(store)
     return store
   end
-  @mem_storage = StrokeDB::MemoryStorage.new
   @path = TEMP_STORAGES
   FileUtils.rm_rf @path
-  StrokeDB.stub!(:default_store).and_return(StrokeDB::Store.new(:storage =&gt; @mem_storage,:index =&gt; @index, 
-                                                                :path =&gt; @path))
+
+  @storage = if ENV['STORAGE'].to_s.downcase == 'file'
+    StrokeDB::FileStorage.new(:path =&gt; @path + '/file_storage')
+  else
+    StrokeDB::MemoryStorage.new
+  end
+
+  $store = StrokeDB::Store.new(:storage =&gt; @storage,:index =&gt; @index, :path =&gt; @path)
+  StrokeDB.stub!(:default_store).and_return($store)
   StrokeDB.default_store
 end
 
@@ -34,4 +40,19 @@ def setup_index(store=nil)
   @index.document_store = store
   store.index_store = @index
   @index
+end
+
+Spec::Runner.configure do |config|
+  config.after(:all) do
+    
+    if ENV['STORAGE'].to_s.downcase == 'file'
+      ObjectSpace.each_object do |obj|
+        obj.stop_autosync! if obj.is_a?(Store)
+      end
+      
+      ObjectSpace.each_object do |obj|
+        obj.close if obj.is_a?(::File) rescue nil
+      end
+    end
+  end
 end
\ No newline at end of file</diff>
      <filename>spec/spec_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,82 +1,5 @@
-require 'rubygems'
-require 'inline'
-
-class Object
-  inline(:C) do |builder|
-    builder.prefix %{
-      static VALUE
-      rb_obj_dummy()
-      {
-          return Qnil;
-      }
-    }
-    builder.add_to_init %{
-      rb_define_private_method(rb_cModule, &quot;unextended&quot;, rb_obj_dummy, 1);
-    }
-    builder.c %{
-      VALUE unextend(VALUE mod) 
-      {
-        VALUE p, prev;
-        Check_Type(mod, T_MODULE);
-        if (mod == rb_mKernel) 
-          rb_raise(rb_eArgError, &quot;unextending Kernel is prohibited&quot;);
-      	
-      	
-        p = rb_singleton_class(self);
-        
-        while (p) {
-            if (p == mod || RCLASS(p)-&gt;m_tbl == RCLASS(mod)-&gt;m_tbl) {
-                RCLASS(prev)-&gt;super = RCLASS(p)-&gt;super;
-                rb_clear_cache();
-                rb_funcall(mod, rb_intern(&quot;unextended&quot;), 1, self);
-                return self;
-            }
-            prev = p;
-            p = RCLASS(p)-&gt;super;
-        }
-        return self;
-      }
-    }
-  end
-
-end
-
-class Class
-  
-  inline(:C) do |builder|
-    builder.prefix %{
-      static VALUE
-      rb_obj_dummy()
-      {
-          return Qnil;
-      }
-    }
-    builder.add_to_init %{
-        rb_define_private_method(rb_cModule, &quot;unincluded&quot;, rb_obj_dummy, 1);
-    }
-    builder.c %{  
-      VALUE uninclude(VALUE mod) 
-      {
-        VALUE p, prev;
-        Check_Type(mod, T_MODULE);
-        if (mod == rb_mKernel) 
-          rb_raise(rb_eArgError, &quot;unincluding Kernel is prohibited&quot;);
-
-        p = self;
-        
-        while (p) {
-            if (p == mod || RCLASS(p)-&gt;m_tbl == RCLASS(mod)-&gt;m_tbl) {
-                RCLASS(prev)-&gt;super = RCLASS(p)-&gt;super;
-                rb_clear_cache();
-                rb_funcall(mod, rb_intern(&quot;unincluded&quot;), 1, self);
-                return self;
-            }
-            prev = p;
-            p = RCLASS(p)-&gt;super;
-        }
-        return self;
-      }
-    }
-  end
-
-end
+if defined?(RUBY_ENGINE) &amp;&amp; RUBY_ENGINE == &quot;rbx&quot;
+  require File.join(File.dirname(__FILE__),'rbxmodexcl')
+else
+  require File.join(File.dirname(__FILE__),'mrimodexcl')
+end
\ No newline at end of file</diff>
      <filename>vendor/rbmodexcl/rbmodexcl.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>23dceb611ce12e262177fad9f3fcb73f089d0b6a</id>
    </parent>
    <parent>
      <id>7732e761b7802b7435f4dd97d01912c88785f3f6</id>
    </parent>
  </parents>
  <author>
    <name>Yurii Rashkovskii</name>
    <email>yrashk@idbns.com</email>
  </author>
  <url>http://github.com/yrashk/strokedb/commit/aa68457b31df9ffda318b2f6d0512ba775f52559</url>
  <id>aa68457b31df9ffda318b2f6d0512ba775f52559</id>
  <committed-date>2008-05-22T16:47:53-07:00</committed-date>
  <authored-date>2008-05-22T16:47:53-07:00</authored-date>
  <message>Merge branch 'master' into index-slots</message>
  <tree>90646e11690e468e06e9e61fa4e2722ee1cdfc47</tree>
  <committer>
    <name>Yurii Rashkovskii</name>
    <email>yrashk@idbns.com</email>
  </committer>
</commit>
