use correct ObjectID generation - no change to ordering yet though
This commit is contained in:
parent
496af2be9c
commit
e05c9fc5da
@ -15,6 +15,8 @@
|
|||||||
# ++
|
# ++
|
||||||
|
|
||||||
require 'mutex_m'
|
require 'mutex_m'
|
||||||
|
require 'socket'
|
||||||
|
require 'digest/md5'
|
||||||
require 'mongo/util/byte_buffer'
|
require 'mongo/util/byte_buffer'
|
||||||
|
|
||||||
module Mongo
|
module Mongo
|
||||||
@ -41,10 +43,6 @@ module Mongo
|
|||||||
# 10
|
# 10
|
||||||
# 11
|
# 11
|
||||||
class ObjectID
|
class ObjectID
|
||||||
|
|
||||||
MACHINE = ( val = rand(0x1000000); [val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff] )
|
|
||||||
PID = ( val = rand(0x10000); [val & 0xff, (val >> 8) & 0xff]; )
|
|
||||||
|
|
||||||
# The string representation of an OID is different than its internal
|
# The string representation of an OID is different than its internal
|
||||||
# and BSON byte representations. The BYTE_ORDER here maps
|
# and BSON byte representations. The BYTE_ORDER here maps
|
||||||
# internal/BSON byte position (the index in BYTE_ORDER) to the
|
# internal/BSON byte position (the index in BYTE_ORDER) to the
|
||||||
@ -56,7 +54,6 @@ module Mongo
|
|||||||
LOCK = Object.new
|
LOCK = Object.new
|
||||||
LOCK.extend Mutex_m
|
LOCK.extend Mutex_m
|
||||||
|
|
||||||
@@index_time = Time.new.to_i
|
|
||||||
@@index = 0
|
@@index = 0
|
||||||
|
|
||||||
# Given a string representation of an ObjectID, return a new ObjectID
|
# Given a string representation of an ObjectID, return a new ObjectID
|
||||||
@ -78,9 +75,8 @@ module Mongo
|
|||||||
end
|
end
|
||||||
|
|
||||||
# +data+ is an array of bytes. If nil, a new id will be generated.
|
# +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)
|
||||||
def initialize(data=nil, t=nil)
|
@data = data || generate
|
||||||
@data = data || generate_id(t)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def eql?(other)
|
def eql?(other)
|
||||||
@ -100,34 +96,39 @@ module Mongo
|
|||||||
str
|
str
|
||||||
end
|
end
|
||||||
|
|
||||||
# (Would normally be private, but isn't so we can test it.)
|
private
|
||||||
def generate_id(t=nil)
|
|
||||||
t ||= Time.new.to_i
|
def generate
|
||||||
|
# 4 bytes current time
|
||||||
|
time = Time.new.to_i
|
||||||
buf = ByteBuffer.new
|
buf = ByteBuffer.new
|
||||||
buf.put_int(t & 0xffffffff)
|
buf.put_int(time & 0xFFFFFFFF)
|
||||||
buf.put_array(MACHINE)
|
|
||||||
buf.put_array(PID)
|
# 3 bytes machine
|
||||||
i = index_for_time(t)
|
machine_hash = Digest::MD5.digest(Socket.gethostname)
|
||||||
buf.put(i & 0xff)
|
buf.put(machine_hash[0])
|
||||||
buf.put((i >> 8) & 0xff)
|
buf.put(machine_hash[1])
|
||||||
buf.put((i >> 16) & 0xff)
|
buf.put(machine_hash[2])
|
||||||
|
|
||||||
|
# 2 bytes pid
|
||||||
|
pid = Process.pid % 0xFFFF
|
||||||
|
buf.put(pid & 0xFF)
|
||||||
|
buf.put((pid >> 8) & 0xFF)
|
||||||
|
|
||||||
|
# 3 bytes inc
|
||||||
|
inc = get_inc
|
||||||
|
buf.put(inc & 0xFF)
|
||||||
|
buf.put((inc >> 8) & 0xFF)
|
||||||
|
buf.put((inc >> 16) & 0xFF)
|
||||||
|
|
||||||
buf.rewind
|
buf.rewind
|
||||||
buf.to_a.dup
|
buf.to_a.dup
|
||||||
end
|
end
|
||||||
|
|
||||||
# (Would normally be private, but isn't so we can test it.)
|
def get_inc
|
||||||
def index_for_time(t)
|
|
||||||
LOCK.mu_synchronize {
|
LOCK.mu_synchronize {
|
||||||
if t != @@index_time
|
@@index = (@@index + 1) % 0xFFFFFF
|
||||||
@@index = 0
|
|
||||||
@@index_time = t
|
|
||||||
end
|
|
||||||
retval = @@index
|
|
||||||
@@index += 1
|
|
||||||
retval
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -7,41 +7,19 @@ class ObjectIDTest < Test::Unit::TestCase
|
|||||||
include Mongo
|
include Mongo
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
@t = 42
|
@o = ObjectID.new()
|
||||||
@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
|
end
|
||||||
|
|
||||||
def test_different
|
def test_different
|
||||||
o2 = ObjectID.new(nil, @t)
|
a = ObjectID.new
|
||||||
assert @o.to_a != o2.to_a
|
b = ObjectID.new
|
||||||
|
assert_not_equal a.to_a, b.to_a
|
||||||
|
assert_not_equal a, b
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_eql?
|
def test_eql?
|
||||||
o2 = ObjectID.new(@o.to_a)
|
o2 = ObjectID.new(@o.to_a)
|
||||||
assert @o.eql?(o2)
|
assert_equal @o, o2
|
||||||
assert @o == o2
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_to_s
|
def test_to_s
|
||||||
|
Loading…
Reference in New Issue
Block a user