uuid 2.2.0 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (7) hide show
  1. data/CHANGELOG +6 -0
  2. data/README.rdoc +24 -5
  3. data/Rakefile +0 -18
  4. data/bin/uuid +55 -0
  5. data/lib/uuid.rb +129 -2
  6. data/uuid.gemspec +3 -1
  7. metadata +29 -13
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ 2.3.0 (2010-04-07)
2
+ * Added: UUID.generator returns the current UUID generator. Particularly useful for calling
3
+ next_sequence on the generator when forking a process.
4
+ * Added: UUID::Server and UUID::Client so you can have one process serving you UUIDs.
5
+ * Added: UUID command line tool. Yay!
6
+
1
7
  2.2.0 (2010-02-18)
2
8
  * Added: set UUID.state_file = false if you cannot use a state file (e.g. shared hosting environment)
3
9
 
@@ -76,15 +76,34 @@ Engine) you can simple turn it off:
76
76
 
77
77
  State files are not portable across machines.
78
78
 
79
+ Note: when using a forking server (Unicorn, Resque, Pipemaster, etc) you don't
80
+ want your forked processes using the same sequence number. Make sure to
81
+ increment the sequence number each time a worker forks.
79
82
 
80
- == Latest and Greatest
83
+ For example, in config/unicorn.rb:
84
+
85
+ after_fork do |server, worker|
86
+ UUID.generator.next_sequence
87
+ end
88
+
89
+
90
+ == Command Line
91
+
92
+ You can run uuid from the command line, generating new UUID to stdout:
81
93
 
82
- Stable release are made through RubyForge, to upgrade simply:
94
+ $ uuid
83
95
 
84
- gem upgrade uuid
96
+ Multiple UUIDs in a sequence, separated with a newline:
85
97
 
86
- You can subscribe for notifications of new releases through the reliable-msg
87
- project page at http://rubyforge.org/projects/reliable-msg
98
+ $ uuid --count 10
99
+
100
+ You can also run client and server from the command line
101
+
102
+ $ uuid --server &
103
+ $ uuid --socket /var/lib/uuid.sock
104
+
105
+
106
+ == Latest and Greatest
88
107
 
89
108
  Source code and documentation hosted on Github: http://github.com/assaf/uuid
90
109
 
data/Rakefile CHANGED
@@ -8,24 +8,6 @@ desc "Default Task"
8
8
  task :default => :test
9
9
 
10
10
 
11
- desc "If you're building from sources, run this task first to setup the necessary dependencies"
12
- task 'setup' do
13
- missing = spec.dependencies.select { |dep| Gem::SourceIndex.from_installed_gems.search(dep).empty? }
14
- missing.each do |dep|
15
- if Gem::SourceIndex.from_installed_gems.search(dep).empty?
16
- puts "Installing #{dep.name} ..."
17
- rb_bin = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
18
- args = []
19
- args << rb_bin << '-S' << 'gem' << 'install' << dep.name
20
- args << '--version' << dep.version_requirements.to_s
21
- args << '--source' << 'http://gems.rubyforge.org'
22
- args << '--install-dir' << ENV['GEM_HOME'] if ENV['GEM_HOME']
23
- sh *args
24
- end
25
- end
26
- end
27
-
28
-
29
11
  desc "Run all test cases"
30
12
  Rake::TestTask.new do |test|
31
13
  test.verbose = true
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+ require "uuid"
3
+ require "optparse"
4
+
5
+ address = nil
6
+ count = 1
7
+ format = :default
8
+ server = false
9
+
10
+ opts = OptionParser.new("", 24, ' ') do |opts|
11
+ opts.banner = "Usage: #{File.basename($0)} [options]"
12
+
13
+ opts.separator "\nOptions:"
14
+ opts.on("-s", "--socket {HOST:PORT|PATH}",
15
+ "communicate on HOST:PORT or PATH (default: #{UUID::SOCKET_NAME})") do |value|
16
+ address = value
17
+ end
18
+
19
+ opts.on("-S", "--server", "run as a server") do |value|
20
+ server = value ? true : false
21
+ end
22
+
23
+ opts.on("-F", "--format {FORMAT}", "UUID format (client only)") do |value|
24
+ format = value.to_sym
25
+ end
26
+
27
+ opts.on("-C", "--count {COUNT}", "returns give number of UUIDs") do |value|
28
+ count = value.to_i
29
+ end
30
+
31
+ opts.on("-h", "--help", "Show this message") do
32
+ puts opts.to_s.gsub(/^.*DEPRECATED.*$/s, '')
33
+ exit
34
+ end
35
+
36
+ opts.on("-v", "--version", "Show version") do
37
+ puts "UUID v#{UUID::VERSION}"
38
+ exit
39
+ end
40
+
41
+ opts.parse! ARGV
42
+ end
43
+
44
+
45
+ if server
46
+ $stdout << "Starting UUID server on #{address}\n"
47
+ UUID::Server.new.listen(address || UUID::SOCKET_NAME)
48
+ else
49
+ UUID.server = address if address
50
+ $stdout << UUID.generate(format)
51
+ (count - 1).times do
52
+ $stdout.putc "\n"
53
+ $stdout << UUID.generate(format)
54
+ end
55
+ end
@@ -9,8 +9,7 @@
9
9
  require 'fileutils'
10
10
  require 'thread'
11
11
  require 'tmpdir'
12
-
13
- require 'rubygems'
12
+ require 'socket'
14
13
  require 'macaddr'
15
14
 
16
15
 
@@ -122,6 +121,24 @@ class UUID
122
121
  @uuid.generate format
123
122
  end
124
123
 
124
+ ##
125
+ # Returns the UUID generator used by generate. Useful if you need to mess
126
+ # with it, e.g. force next sequence when forking (e.g. Unicorn, Resque):
127
+ #
128
+ # after_fork do
129
+ # UUID.generator.next_sequence
130
+ # end
131
+ def self.generator
132
+ @uuid ||= new
133
+ end
134
+
135
+ ##
136
+ # Call this to use a UUID Server. Expects address to bind to (SOCKET_NAME is
137
+ # a good default)
138
+ def self.server=(address)
139
+ @uuid = Client.new(address) unless Client === @uuid
140
+ end
141
+
125
142
  ##
126
143
  # Creates an empty state file in /var/tmp/ruby-uuid or the windows common
127
144
  # application data directory using mode 0644. Call with a different mode
@@ -313,4 +330,114 @@ protected
313
330
  io.write [mac1, mac2, @sequence, @last_clock].pack(STATE_FILE_FORMAT)
314
331
  end
315
332
 
333
+
334
+ # You don't have to use this, it's just a good default.
335
+ SOCKET_NAME ="/var/lib/uuid.sock"
336
+
337
+ # With UUID server you don't have to worry about multiple processes
338
+ # synchronizing over the state file, calling next_sequence when forking a
339
+ # process and other things you're probably not worried about (because
340
+ # statistically they're very unlikely to break your code).
341
+ #
342
+ # But if you are worried about and thought to yourself, "what would a simple
343
+ # UUID server look like?", here's the answer. The protocol is dead simple:
344
+ # client sends a byte, server responds with a UUID. Can use TCP or domain
345
+ # sockets.
346
+ class Server
347
+
348
+ # Create new server. Nothing interesting happens until you call listen.
349
+ def initialize()
350
+ @generator = UUID.new
351
+ end
352
+
353
+ # Start the server listening on the specific address. Blocks and never
354
+ # returns. Address can be:
355
+ # - A Socket object
356
+ # - UNIX domain socket name (e.g. /var/run/uuid.sock, must start with /)
357
+ # - IP address, colon, port (e.g. localhost:1337)
358
+ def listen(address)
359
+ sock = bind(address)
360
+ while client = sock.accept
361
+ Thread.start(client) do |client|
362
+ while client.read 1
363
+ client.write @generator.generate
364
+ end
365
+ end
366
+ end
367
+ end
368
+
369
+ # Returns UNIXServer or TCPServer from address. Returns argument if not a
370
+ # string, so can pass through (see #listen).
371
+ def bind(address)
372
+ return address unless String === address
373
+ if address[0] == ?/
374
+ if File.exist?(address)
375
+ raise ArgumentError, "#{address} is not a socket" unless File.socket?(address)
376
+ File.unlink(address)
377
+ end
378
+ sock = UNIXServer.new(address)
379
+ File.chmod 0666, address
380
+ elsif address =~ /^(\d+\.\d+\.\d+\.\d+):(\d+)$/
381
+ sock = TCPServer.new($1, $2.to_i)
382
+ else
383
+ raise ArgumentError, "Don't know how to bind #{address}"
384
+ end
385
+ sock.setsockopt(IPPROTO_TCP, TCP_NODELAY, 1) if defined?(TCP_NODELAY)
386
+ sock
387
+ end
388
+
389
+ end
390
+
391
+
392
+ # Every server needs a client. Client provides you with the single ultimate
393
+ # method: #generate. Typically you'll use this instead of the local UUID
394
+ # generator:
395
+ # UUID.server = UUID::SOCKET_NAME
396
+ class Client
397
+
398
+ def initialize(address)
399
+ @socket = connect(address)
400
+ at_exit { close }
401
+ end
402
+
403
+ # Talks to server and returns new UUID in specified format.
404
+ def generate(format = :default)
405
+ @socket.write "\0"
406
+ uuid = @socket.read(36)
407
+ return uuid if format == :default
408
+ template = FORMATS[format]
409
+ raise ArgumentError, "invalid UUID format #{format.inspect}" unless template
410
+ template % uuid.split("-").map { |p| p.to_i(16) }
411
+ end
412
+
413
+ # Returns UNIXSocket or TCPSocket from address. Returns argument if not a
414
+ # string, so can pass through.
415
+ def connect(address)
416
+ return address unless String === address
417
+ if address[0] == ?/
418
+ sock = UNIXSocket.new(address)
419
+ elsif address =~ /^(\d+\.\d+\.\d+\.\d+):(\d+)$/
420
+ sock = TCPSocket.new($1, $2.to_i)
421
+ else
422
+ raise ArgumentError, "Don't know how to connect to #{address}"
423
+ end
424
+ sock.setsockopt(IPPROTO_TCP, TCP_NODELAY, 1) if defined?(TCP_NODELAY)
425
+ sock
426
+ end
427
+
428
+ def next_sequence #:nodoc: Stubbed to do nothing.
429
+ end
430
+
431
+ def inspect
432
+ @socket ? "Server on #{Socket.unpack_sockaddr_in(@socket.getsockname).reverse!.join(':')}" : "Connection closed"
433
+ end
434
+
435
+ # Close the socket.
436
+ def close
437
+ @socket.shutdown if @socket
438
+ @socket = nil
439
+ end
440
+
441
+ end
442
+
316
443
  end
@@ -1,6 +1,6 @@
1
1
  spec = Gem::Specification.new do |spec|
2
2
  spec.name = 'uuid'
3
- spec.version = '2.2.0'
3
+ spec.version = '2.3.0'
4
4
  spec.summary = "UUID generator"
5
5
  spec.description = <<-EOF
6
6
  UUID generator for producing universally unique identifiers based on RFC 4122
@@ -12,6 +12,8 @@ EOF
12
12
  spec.homepage = 'http://github.com/assaf/uuid'
13
13
 
14
14
  spec.files = Dir['{bin,test,lib,docs}/**/*'] + ['README.rdoc', 'MIT-LICENSE', 'Rakefile', 'CHANGELOG', 'uuid.gemspec']
15
+ spec.executables = "uuid"
16
+
15
17
  spec.has_rdoc = true
16
18
  spec.rdoc_options << '--main' << 'README.rdoc' << '--title' << 'UUID generator' << '--line-numbers'
17
19
  '--webcvs' << 'http://github.com/assaf/uuid'
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uuid
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ prerelease: false
5
+ segments:
6
+ - 2
7
+ - 3
8
+ - 0
9
+ version: 2.3.0
5
10
  platform: ruby
6
11
  authors:
7
12
  - Assaf Arkin
@@ -10,29 +15,36 @@ autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
17
 
13
- date: 2010-02-18 00:00:00 -08:00
18
+ date: 2010-04-07 00:00:00 -07:00
14
19
  default_executable:
15
20
  dependencies:
16
21
  - !ruby/object:Gem::Dependency
17
22
  name: macaddr
18
- type: :runtime
19
- version_requirement:
20
- version_requirements: !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
21
25
  requirements:
22
26
  - - ~>
23
27
  - !ruby/object:Gem::Version
28
+ segments:
29
+ - 1
30
+ - 0
24
31
  version: "1.0"
25
- version:
26
- description: UUID generator for producing universally unique identifiers based on RFC 4122 (http://www.ietf.org/rfc/rfc4122.txt).
27
- email: assaf@labnotes.org
28
- executables: []
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ description: |
35
+ UUID generator for producing universally unique identifiers based on RFC 4122
36
+ (http://www.ietf.org/rfc/rfc4122.txt).
29
37
 
38
+ email: assaf@labnotes.org
39
+ executables:
40
+ - uuid
30
41
  extensions: []
31
42
 
32
43
  extra_rdoc_files:
33
44
  - README.rdoc
34
45
  - MIT-LICENSE
35
46
  files:
47
+ - bin/uuid
36
48
  - test/test-uuid.rb
37
49
  - lib/uuid.rb
38
50
  - README.rdoc
@@ -42,6 +54,8 @@ files:
42
54
  - uuid.gemspec
43
55
  has_rdoc: true
44
56
  homepage: http://github.com/assaf/uuid
57
+ licenses: []
58
+
45
59
  post_install_message:
46
60
  rdoc_options:
47
61
  - --main
@@ -55,20 +69,22 @@ required_ruby_version: !ruby/object:Gem::Requirement
55
69
  requirements:
56
70
  - - ">="
57
71
  - !ruby/object:Gem::Version
72
+ segments:
73
+ - 0
58
74
  version: "0"
59
- version:
60
75
  required_rubygems_version: !ruby/object:Gem::Requirement
61
76
  requirements:
62
77
  - - ">="
63
78
  - !ruby/object:Gem::Version
79
+ segments:
80
+ - 0
64
81
  version: "0"
65
- version:
66
82
  requirements: []
67
83
 
68
84
  rubyforge_project:
69
- rubygems_version: 1.3.1
85
+ rubygems_version: 1.3.6
70
86
  signing_key:
71
- specification_version: 2
87
+ specification_version: 3
72
88
  summary: UUID generator
73
89
  test_files: []
74
90