Skip to content

Commit

Permalink
resolved conflict in a view_storage.rb
Browse files Browse the repository at this point in the history
  • Loading branch information
Oleg Andreev committed Apr 27, 2008
2 parents 9b327d7 + ae507d7 commit 7d27f84
Show file tree
Hide file tree
Showing 5 changed files with 268 additions and 30 deletions.
3 changes: 2 additions & 1 deletion lib/strokedb/views.rb
@@ -1,3 +1,4 @@
require 'views/view'
require 'views/default_key_encoder'
require 'views/raw_data_meta'
require 'views/raw_data_meta'
require 'views/view_storage'
44 changes: 26 additions & 18 deletions lib/strokedb/views/view.rb
@@ -1,5 +1,5 @@
module StrokeDB
View = Meta.new do
View = Meta.new(:nsurl => STROKEDB_NSURL) do

DEFAULT_VIEW_OPTIONS = {
# Declare the size for a key to use optimized index file
Expand Down Expand Up @@ -118,8 +118,9 @@ def ugly_find(start_key, end_key, key, limit, offset, reverse, with_keys)
end_key = start_key = key
end

array = storage.find(encode_key(start_key),
array = storage.find(start_key && encode_key(start_key),
end_key && encode_key(end_key),
encode_key(key),
limit,
offset,
reverse,
Expand Down Expand Up @@ -151,25 +152,34 @@ def update(doc)
storage.set_options(:key_size => key_size,
:value_size => value_size,
:on_duplicate_key => on_duplicate_key)

if self["strategy"] == "heads"
class << self
alias_method :update, :update_head
public :update
end

if self['strategy'] == "heads"
update_head(doc)
else
class << self
alias_method :update, :update_version
public :update
end
update_version(doc)
end
update(doc)
# Way to optimize update! execution time (if it will matter)
# Please note that it will make persistent changes to a view instance object
# Here we go:
#
# if self["strategy"] == "heads"
# class << self
# alias_method :update, :update_head
# public :update
# end
# else
# class << self
# alias_method :update, :update_version
# public :update
# end
# end
#update(doc)
end

# Remove a previous version, add a new one.
#
def update_head(doc) #:nodoc
prev = doc.versions.previous
prev = doc.versions.previous # FIXME: handle situation with no previous version
old_pairs = map_with_encoding(prev.uuid, prev)
new_pairs = map_with_encoding(doc.uuid, doc)
storage.replace(old_pairs, new_pairs)
Expand All @@ -192,7 +202,8 @@ def map_with_encoding(key, value)
private :map_with_encoding

def storage
@storage ||= store.view_storages[self.uuid]
# @storage ||= store.view_storages[self.uuid]
@storage ||= ViewStorage.new
end
private :storage

Expand Down Expand Up @@ -225,9 +236,6 @@ def split_by(json_key)
end
end

# Syntactic sugar for Views["view_name"]
Views = View

class << View
def [](name)
# TODO: find viewdoc by name
Expand Down
53 changes: 44 additions & 9 deletions lib/strokedb/views/view_storage.rb
Expand Up @@ -5,49 +5,84 @@ class ViewStorage
def initialize(options = {})
# TODO: find out whether the view indexfile exists and read
# its options

@skiplist = SearchSkiplist.new

end

def set_options(options)
if exists? && self.options != options
raise StandardError, "Couldn't change options for an existing storage!"
end

self.options = options
@options = options

end

#
#
def find(start_key, end_key, limit, offset, reverse, with_keys)
# how smart...
def oleganza_find(start_key, end_key, limit, offset, reverse, with_keys)
@skiplist.search(start_key, end_key, limit, offset, reverse, with_keys)
end

#
#
def find(start_key, end_key, key, limit, offset, reverse, with_keys)
start_key = end_key = key if start_key.nil? && end_key.nil?
# Please note that below algorithm will most probably be eventually replaced by a new skiplist Oleg Andreev works on currently
start_key = @skiplist.first_key unless start_key
current_key = start_key
offset ||= 0

items = []
item = @skiplist.find_nearest_node(current_key)

offset.times do
item = item[0][0] # next node
end

until item.nil?
items << (with_keys ? [item[1],item[2]] : item[2]) # [1] is a node_key [2] is a node_value
break if (current_key = item[1]) == end_key
break if items.size == limit
item = item[0][0] # next node
end

items
end

#
#
def replace(old_pairs, new_pairs)

old_pairs.each do |pair|
key, value = pair
@skiplist.insert(key,nil) if @skiplist.find(key)
end
insert(new_pairs)
end

#
#
def insert(new_pairs)

new_pairs.each do |pair|
key, value = pair
@skiplist.insert(key, value)
end
end

#
#
def exists?

true
end

#
#
def clear!

@skiplist = SimpleSkiplist.new
end

def empty?
@skiplist.empty?
end

end
end
2 changes: 0 additions & 2 deletions spec/lib/strokedb/views/view_spec.rb
Expand Up @@ -40,8 +40,6 @@ def view.map(key, value)
@post_comments.map(123,123).should == [ [ 123, 123 ] ]
end



end


196 changes: 196 additions & 0 deletions spec/lib/strokedb/views/view_storage_spec.rb
@@ -0,0 +1,196 @@
require File.dirname(__FILE__) + '/spec_helper'

describe "New", ViewStorage do

before(:each) do
@view_storage = ViewStorage.new
end

it "should be empty" do
@view_storage.should be_empty
end
end

describe "Inserting single pair into", ViewStorage do

before(:each) do
setup_default_store
@view_storage = ViewStorage.new
@insertion = lambda {|key, val| @view_storage.insert([[key, val]]) }
end

it "should store reference to Document" do
@value = Document.new
@insertion.call('key',@value)
@view_storage.find(nil, nil, 'key', nil, nil, false, false).to_set.should == [@value].to_set
end

it "should store reference to an arbitrary data" do
@value = "some data"
@insertion.call('key',@value)
@view_storage.find(nil, nil, 'key', nil, nil, false, false).to_set.should == [@value].to_set
end

end

describe "Inserting multiple pairs into", ViewStorage do

before(:each) do
setup_default_store
@view_storage = ViewStorage.new
@insertion = lambda do |keys, vals|
pairs = []
keys.each_with_index {|key, i| pairs << [key, vals[i]]}
@view_storage.insert(pairs)
end
end

it "should store references to Documents" do
@value_1 = Document.new
@value_2 = Document.new
@insertion.call(['key','another_key'],[@value_1, @value_2])
@view_storage.find('another_key', 'key', nil, nil, nil, false, false).to_set.should == [@value_1, @value_2].to_set
end

it "should store references to an arbitrary data items" do
@value_1 = "some data"
@value_2 = "another data"
@insertion.call(['key','another_key'],[@value_1, @value_2])
@view_storage.find('another_key', 'key', nil, nil, nil, false, false).to_set.should == [@value_1, @value_2].to_set
end

end


describe "Replacing single pair in", ViewStorage do

before(:each) do
setup_default_store
@view_storage = ViewStorage.new
@insertion = lambda {|key, val| @view_storage.insert([[key, val]]) }
@replacement = lambda {|oldkey, oldval, key, val| @view_storage.replace([[oldkey, oldval]],[[key, val]]) }
end

it "should replace existing reference to Document if such pair exists already" do
@value_1 = Document.new
@value_2 = Document.new

@insertion.call('key',@value_1)
@replacement.call('key',@value_1, 'key',@value_2)

@view_storage.find(nil, nil, 'key', nil, nil, false, false).to_set.should == [@value_2].to_set
end

it "should replace existing reference to an arbitrary data item if such pair exists already" do
@value_1 = "some data"
@value_2 = "another data"

@insertion.call('key',@value_1)
@replacement.call('key',@value_1, 'key',@value_2)

@view_storage.find(nil, nil, 'key', nil, nil, false, false).to_set.should == [@value_2].to_set
end

end

describe "Replacing multiple pairs in", ViewStorage do

before(:each) do
setup_default_store
@view_storage = ViewStorage.new
@insertion = lambda do |keys, vals|
pairs = []
keys.each_with_index {|key, i| pairs << [key, vals[i]]}
@view_storage.insert(pairs)
end
@replacement = lambda do |oldkeys, oldvals, keys, vals|
old_pairs = []
new_pairs = []
oldkeys.each_with_index {|key, i| old_pairs << [key, oldvals[i]]}
keys.each_with_index {|key, i| new_pairs << [key, vals[i]]}

@view_storage.replace(old_pairs, new_pairs)
end
end

it "should replace existing references to Document if such pairs exist already" do
@value_1 = Document.new
@value_2 = Document.new

@insertion.call(['key','another_key'],[@value_1, @value_2])
@replacement.call(['key','another_key'],[@value_1, @value_2],['key','another_key'],[@value_2, @value_1])

@view_storage.find(nil, nil, 'key', nil, nil, false, false).to_set.should == [@value_2].to_set
@view_storage.find(nil, nil, 'another_key', nil, nil, false, false).to_set.should == [@value_1].to_set
end

it "should replace existing references to an arbitrary data item if such pairs exist already" do
@value_1 = "some data"
@value_2 = "another data"

@value_1 = "some data"
@value_2 = "another data"
@insertion.call(['key','another_key'],[@value_1, @value_2])
@replacement.call(['key','another_key'],[@value_1, @value_2], ['key','another_key'],[@value_2, @value_1])

@view_storage.find(nil, nil, 'key', nil, nil, false, false).to_set.should == [@value_2].to_set
@view_storage.find(nil, nil, 'another_key', nil, nil, false, false).to_set.should == [@value_1].to_set
end

end

describe ViewStorage, "with some pairs inserted" do

before(:each) do
setup_default_store
@view_storage = ViewStorage.new
@view_storage.insert((1..100).to_a.map {|i| [DefaultKeyEncoder.encode(i),i]})
end

it "should not be empty" do
@view_storage.should_not be_empty
end

it "should be empty after clearance" do
@view_storage.clear!
@view_storage.should be_empty
end

it "should be able to find entry with specific key" do
@view_storage.find(nil, nil, DefaultKeyEncoder.encode(50), nil, nil, false, false).to_set.should == [50].to_set
end

it "should be able to find entries with specific key range" do
@view_storage.find(DefaultKeyEncoder.encode(3), DefaultKeyEncoder.encode(77), nil, nil, nil, false, false).to_set.should == (3..77).to_set
end

it "should be able to find entries with only start boundary range" do
@view_storage.find(DefaultKeyEncoder.encode(77), nil, nil, nil, nil, false, false).to_set.should == (77..100).to_set
end

it "should be able to find entries with only end boundary range" do
@view_storage.find(nil, DefaultKeyEncoder.encode(77), nil, nil, nil, false, false).to_set.should == (1..77).to_set
end

it "should be able to limit results if there is more results than allowed" do
@view_storage.find(DefaultKeyEncoder.encode(3), DefaultKeyEncoder.encode(77), nil, 50, nil, false, false).to_set.should == (3..52).to_set
end

it "should not limit results if there is less results than allowed" do
@view_storage.find(DefaultKeyEncoder.encode(3), DefaultKeyEncoder.encode(77), nil, 100, nil, false, false).to_set.should == (3..77).to_set
end

it "should not skip some results if offset is 0 or nil" do
@view_storage.find(DefaultKeyEncoder.encode(3), DefaultKeyEncoder.encode(77), nil, nil, nil, false, false).to_set.should == (3..77).to_set
@view_storage.find(DefaultKeyEncoder.encode(3), DefaultKeyEncoder.encode(77), nil, nil, 0, false, false).to_set.should == (3..77).to_set
end

it "should skip some results if offset is specified" do
@view_storage.find(DefaultKeyEncoder.encode(3), DefaultKeyEncoder.encode(77), nil, nil, 3, false, false).to_set.should == (6..77).to_set
end

it "should return both keys and values if told so" do
@view_storage.find(DefaultKeyEncoder.encode(3), DefaultKeyEncoder.encode(77), nil, nil, nil, false, true).to_set.should == (3..77).to_a.map {|i| [DefaultKeyEncoder.encode(i),i]}.to_set
end

end

0 comments on commit 7d27f84

Please sign in to comment.