Method: UUID.new

Defined in:
lib/cast_off/compile/namespace/uuid.rb

.new(clock = nil, time = Time.now, mac_addr = nil) ⇒ Object

create the “version 1” UUID with current system clock, current UTC timestamp, and the IEEE 802 address (so-called MAC address).

Speed notice: it’s slow. It writes some data into hard drive on every invokation. If you want to speed this up, try remounting tmpdir with a memory based filesystem (such as tmpfs). STILL slow? then no way but rewrite it with c :)



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/cast_off/compile/namespace/uuid.rb', line 134

def new clock=nil, time=Time.now, mac_addr=nil
  c = t = m = nil
  Dir.chdir Dir.tmpdir do
    unless FileTest.exist? STATE_FILE then
      # Generate a pseudo MAC address because we have no pure-ruby way
      # to know  the MAC  address of the  NIC this system  uses.  Note
      # that cheating  with pseudo arresses here  is completely legal:
      # see Section 4.5 of RFC4122 for details.
      sha1 = Digest::SHA1.new
      256.times do
        r = [prand].pack "N"
        sha1.update r
      end
      str = sha1.digest
      r = rand 34 # 40-6
      node = str[r, 6] || str
      node = node.bytes.to_a
      node[0] |= 0x01 # multicast bit
      node = node.pack "C*"
      k = rand 0x40000
      open STATE_FILE, 'w' do |fp|
        fp.flock IO::LOCK_EX
        write_state fp, k, node
        fp.chmod 0o777 # must be world writable
      end
    end
    open STATE_FILE, 'r+' do |fp|
      fp.flock IO::LOCK_EX
      c, m = read_state fp
      c += 1 # important; increment here
      write_state fp, c, m
    end
  end
  c = clock & 0b11_1111_1111_1111 if clock
  m = mac_addr if mac_addr
  time = Time.at time if time.is_a? Float
  case time
  when Time
    t = time.to_i * 10_000_000 + time.tv_usec * 10 + UNIXEpoch
  when Integer
    t = time + UNIXEpoch
  else
    raise TypeError, "cannot convert ``#{time}'' into Time."
  end

  tl = t & 0xFFFF_FFFF
  tm = t >> 32
  tm = tm & 0xFFFF
  th = t >> 48
  th = th & 0b0000_1111_1111_1111
  th = th | 0b0001_0000_0000_0000
  cl = c & 0b0000_0000_1111_1111
  ch = c & 0b0011_1111_0000_0000
  ch = ch >> 8
  ch = ch | 0b1000_0000
  pack tl, tm, th, ch, cl, m
end