Trying to merge upstream into my code
This commit is contained in:
parent
8bcabd977d
commit
8f90ce7280
|
@ -12,40 +12,87 @@
|
|||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
require 'mongo/util/uuid'
|
||||
require 'mutex_m'
|
||||
require 'mongo/util/byte_buffer'
|
||||
|
||||
module XGen
|
||||
module Mongo
|
||||
module Driver
|
||||
|
||||
# Implementation of the Babble OID.
|
||||
#
|
||||
# 12 bytes
|
||||
# ---
|
||||
# 0 time
|
||||
# 1
|
||||
# 2
|
||||
# 3
|
||||
# 4 machine
|
||||
# 5
|
||||
# 6
|
||||
# 7 pid
|
||||
# 8
|
||||
# 9 inc
|
||||
# 10
|
||||
# 11
|
||||
class ObjectID
|
||||
|
||||
include Comparable
|
||||
|
||||
include Comparable
|
||||
MACHINE = ( val = rand(0x1000000); [val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff] )
|
||||
PID = ( val = rand(0x10000); [val & 0xff, (val >> 8) & 0xff]; )
|
||||
|
||||
@@uuid_generator = UUID.new
|
||||
LOCK = Object.new
|
||||
LOCK.extend Mutex_m
|
||||
|
||||
# String UUID
|
||||
attr_reader :uuid
|
||||
@@index_time = Time.new.to_i
|
||||
@@index = 0
|
||||
|
||||
# +uuid+ is a string. If nil, a new UUID will be generated.
|
||||
def initialize(uuid=nil)
|
||||
# The Babble server expects 12-byte (24 hex character) keys, which
|
||||
# is why we throw away part of the UUID.
|
||||
@uuid ||= @@uuid_generator.generate(:compact).sub(/(.{12}).{8}(.{12})/, '\1\2')
|
||||
# +data+ is an array of bytes. If nil, a new id will be generated.
|
||||
# The time +t+ is only used for testing; leave it nil.
|
||||
def initialize(data=nil, t=nil)
|
||||
@data = data || generate_id(t)
|
||||
end
|
||||
|
||||
def eql?(other)
|
||||
@data == other.to_a
|
||||
end
|
||||
alias_method :==, :eql?
|
||||
|
||||
def to_a
|
||||
@data.dup
|
||||
end
|
||||
|
||||
def to_s
|
||||
@uuid
|
||||
@data.collect { |b| '%02x' % b }.join
|
||||
end
|
||||
|
||||
# This will make more sense when we implement the Babble algorithm for
|
||||
# generating object ids.
|
||||
def <=>(other)
|
||||
to_s <=> other.to_s
|
||||
def generate_id(t=nil)
|
||||
t ||= Time.new.to_i
|
||||
buf = ByteBuffer.new
|
||||
buf.put_int(t & 0xffffffff)
|
||||
buf.put_array(MACHINE)
|
||||
buf.put_array(PID)
|
||||
i = index_for_time(t)
|
||||
buf.put(i & 0xff)
|
||||
buf.put((i >> 8) & 0xff)
|
||||
buf.put((i >> 16) & 0xff)
|
||||
|
||||
buf.rewind
|
||||
buf.to_a.dup
|
||||
end
|
||||
|
||||
def index_for_time(t)
|
||||
LOCK.mu_synchronize {
|
||||
if t != @@index_time
|
||||
@@index = 0
|
||||
@@index_time = t
|
||||
end
|
||||
retval = @@index
|
||||
@@index += 1
|
||||
retval
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -106,21 +106,27 @@ class DBAPITest < Test::Unit::TestCase
|
|||
assert docs.detect { |row| row['a'] == 1 }
|
||||
assert docs.detect { |row| row['a'] == 2 }
|
||||
# Find by advanced query (regexp)
|
||||
docs = @coll.find('a' => {'$in' => /[1|2]/}).map
|
||||
docs = @coll.find('a' => /[1|2]/).map
|
||||
assert_equal 2, docs.size
|
||||
assert docs.detect { |row| row['a'] == 1 }
|
||||
assert docs.detect { |row| row['a'] == 2 }
|
||||
end
|
||||
|
||||
def test_find_sorting
|
||||
@r2 = @coll.insert('_id' => new_oid, 'a' => 2)
|
||||
@r3 = @coll.insert('_id' => new_oid, 'b' => 3)
|
||||
@coll.insert('a' => 2)
|
||||
@coll.insert('b' => 3)
|
||||
|
||||
# Sorting (ascending)
|
||||
docs = @coll.find({'a' => { '$lt' => 10 }}, :sort => { 'a' => 1 }).map
|
||||
order_by = OrderedHash.new
|
||||
order_by['a'] = 1
|
||||
docs = @coll.find({'a' => { '$lt' => 10 }}, :sort => order_by).map
|
||||
assert_equal 2, docs.size
|
||||
assert_equal 1, docs.first['a']
|
||||
|
||||
# Sorting (descending)
|
||||
docs = @coll.find({'a' => { '$lt' => 10 }}, :sort => { 'a' => -1 }).map
|
||||
order_by = OrderedHash.new
|
||||
order_by['a'] = -1
|
||||
docs = @coll.find({'a' => { '$lt' => 10 }}, :sort => order_by).map
|
||||
assert_equal 2, docs.size
|
||||
assert_equal 2, docs.first['a']
|
||||
end
|
||||
|
|
|
@ -6,8 +6,6 @@ require 'test/unit'
|
|||
class DBConnectionTest < Test::Unit::TestCase
|
||||
|
||||
def test_no_exceptions
|
||||
host = ENV['HOST'] || ENV['host'] || 'localhost'
|
||||
port = ENV['PORT'] || ENV['port'] || 27017
|
||||
host = ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost'
|
||||
port = ENV['MONGO_RUBY_DRIVER_PORT'] || XGen::Mongo::Driver::Mongo::DEFAULT_PORT
|
||||
db = XGen::Mongo::Driver::Mongo.new(host, port).db('ruby-mongo-test')
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib')
|
||||
require 'mongo'
|
||||
require 'test/unit'
|
||||
|
||||
class ObjectIDTest < Test::Unit::TestCase
|
||||
|
||||
include XGen::Mongo::Driver
|
||||
|
||||
def setup
|
||||
@t = 42
|
||||
@o = ObjectID.new(nil, @t)
|
||||
end
|
||||
|
||||
def test_index_for_time
|
||||
t = 99
|
||||
assert_equal 0, @o.index_for_time(t)
|
||||
assert_equal 1, @o.index_for_time(t)
|
||||
assert_equal 2, @o.index_for_time(t)
|
||||
t = 100
|
||||
assert_equal 0, @o.index_for_time(t)
|
||||
end
|
||||
|
||||
def test_time_bytes
|
||||
a = @o.to_a
|
||||
assert_equal @t, a[0]
|
||||
3.times { |i| assert_equal 0, a[i+1] }
|
||||
|
||||
t = 43
|
||||
o = ObjectID.new(nil, t)
|
||||
a = o.to_a
|
||||
assert_equal t, a[0]
|
||||
3.times { |i| assert_equal 0, a[i+1] }
|
||||
assert_equal 1, o.index_for_time(t) # 0 was used for o
|
||||
end
|
||||
|
||||
def test_different
|
||||
o2 = ObjectID.new(nil, @t)
|
||||
assert @o.to_a != o2.to_a
|
||||
end
|
||||
|
||||
def test_eql?
|
||||
o2 = ObjectID.new(@o.to_a)
|
||||
assert @o.eql?(o2)
|
||||
assert @o == o2
|
||||
end
|
||||
|
||||
def test_to_s
|
||||
s = @o.to_s
|
||||
assert_equal 24, s.length
|
||||
s =~ /^([0-9a-f]+)$/
|
||||
assert_equal 24, $1.length
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue