Skip to content

Commit

Permalink
SimpleSkiplist: added specs for :reverse and some bugfixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Oleg Andreev committed Apr 28, 2008
1 parent 289e433 commit 0136cb6
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 14 deletions.
32 changes: 18 additions & 14 deletions lib/strokedb/data_structures/simple_skiplist.rb
Expand Up @@ -45,7 +45,6 @@ def empty?
end

# Complicated search algorithm
# TODO: add reverse support
#
def search(start_key, end_key, limit, offset, reverse, with_keys)
offset ||= 0
Expand All @@ -59,22 +58,28 @@ def search(start_key, end_key, limit, offset, reverse, with_keys)
collect_values(start_node, end_key, limit, reverse, with_keys)
end

#
# TODO: add C routins for this to optimize performance
#
def find_by_prefix(start_key, reverse)
# TODO: add reverse support
dir = dir_for_reverse(reverse)
x = anchor(reverse) # head [FIXME: change method name]
x = anchor(reverse)
# if no prefix given, just return a first node
!start_key and return node_next(x, 0, dir)

level = node_level(x)
while level > 0
level -= 1
xnext = node_next(x, level, dir)
while node_compare(xnext, start_key) < 0
x = xnext
xnext = node_next(x, level, dir)
if reverse
while node_compare(xnext, start_key) > 0
x = xnext
xnext = node_next(x, level, dir)
end
else
while node_compare(xnext, start_key) < 0
x = xnext
xnext = node_next(x, level, dir)
end
end
end
xnext == anchor(!reverse) and return nil
Expand All @@ -86,7 +91,7 @@ def find_by_prefix(start_key, reverse)
#
def skip_nodes(node, offset, reverse)
dir = dir_for_reverse(reverse)
tail = @tail
tail = anchor(!reverse)
while offset > 0 && node != tail
node = node_next(node, 0, dir)
offset -= 1
Expand All @@ -105,7 +110,11 @@ def collect_values(x, end_prefix, limit, reverse, with_keys)
end_prefix ||= ""
pfx_size = end_prefix.size
while x != tail
node_key(x)[0, pfx_size] > end_prefix and return values
if reverse
node_key(x)[0, pfx_size] < end_prefix and return values
else
node_key(x)[0, pfx_size] > end_prefix and return values
end
values.size >= limit and return values
values << meth.call(x).freeze
x = node_next(x, 0, dir)
Expand Down Expand Up @@ -400,11 +409,6 @@ def new_node(level, key, value)
]
end

# TODO: drop this after serialization routines updated
def new_anchor
new_node(@maxlevel, nil, nil)
end

def new_anchors(level)
h = new_node(level, nil, nil)
t = new_node(level, nil, nil)
Expand Down
5 changes: 5 additions & 0 deletions spec/lib/strokedb/data_structures/simple_skiplist_spec.rb
Expand Up @@ -260,6 +260,11 @@
r = search_with_options(@list, :reverse => true, :with_keys => true)
r.should == @key_values.reverse
end

it "should find a value in a reversed order" do
r = search_with_options(@list, :start_key => "ab", :end_key => "aa", :reverse => true)
r.should == %w[ab\ value aa\ value]
end

def search_should_yield(results, os = {})
# TODO: added reverse cases
Expand Down
6 changes: 6 additions & 0 deletions spec/lib/strokedb/views/view_spec.rb
Expand Up @@ -69,6 +69,12 @@ def view.map(uuid, doc)
@view.find(:key => @article2).should == [@comment21, @comment22]
@view.find(:key => @article3).should == [ ]
end

it "should find all the article's comments in a reverse order" do
@view.find(:key => @article1, :reverse => true).should == [@comment13, @comment12, @comment11]
@view.find(:key => @article2, :reverse => true).should == [@comment22, @comment21]
@view.find(:key => @article3, :reverse => true).should == [ ]
end

it "should find all the article's comments with limit" do
@view.find(:key => @article1, :limit => 2).should == [@comment11, @comment12]
Expand Down

0 comments on commit 0136cb6

Please sign in to comment.