dcell 0.7.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+ rvm:
2
+ - 1.9.2
3
+ - 1.9.3
4
+ # - rbx crashing :(
5
+ - jruby
6
+ - ruby-head
7
+
8
+ env: "JRUBY_OPTS=--1.9"
data/CHANGES.md CHANGED
@@ -1,3 +1,8 @@
1
+ 0.8.0
2
+ -----
3
+ * Track calls in-flight with DCell::RPC and DCell::RPC::Manager
4
+ * Compatibility changes for Celluloid 0.8.0
5
+
1
6
  0.7.1
2
7
  -----
3
8
  * Bump version to match Celluloid
data/Rakefile CHANGED
@@ -1,4 +1,4 @@
1
1
  require "bundler/gem_tasks"
2
2
  Dir["tasks/**/*.task"].each { |task| load task }
3
3
 
4
- task :default => :spec
4
+ task :default => :spec
@@ -1,3 +1,7 @@
1
+ 0.8.0
2
+ -----
3
+ * Update to match internals of celluloid-io
4
+
1
5
  0.7.0
2
6
  -----
3
7
  * Use celluloid-io gem
@@ -11,8 +11,8 @@ Gem::Specification.new do |gem|
11
11
  gem.name = "celluloid-zmq"
12
12
  gem.version = Celluloid::ZMQ::VERSION
13
13
 
14
- gem.add_dependency "celluloid", ">= 0.7.0"
15
- gem.add_dependency "celluloid-io", ">= 0.7.0"
14
+ gem.add_dependency "celluloid", "~> 0.8.0"
15
+ gem.add_dependency "celluloid-io", "~> 0.8.0"
16
16
  gem.add_dependency "ffi"
17
17
  gem.add_dependency "ffi-rzmq"
18
18
 
@@ -24,15 +24,10 @@ module Celluloid
24
24
  end
25
25
  end
26
26
 
27
- # Wait for the given IO object to become readable
28
- def wait_readable(socket)
29
- # Law of demeter be damned!
30
- current_actor.mailbox.reactor.wait_readable(socket)
31
- end
27
+ extend Forwardable
32
28
 
33
- # Wait for the given IO object to become writeable
34
- def wait_writeable(socket)
35
- current_actor.mailbox.reactor.wait_writeable(socket)
36
- end
29
+ # Wait for the given IO object to become readable/writeable
30
+ def_delegators 'current_actor.mailbox.reactor',
31
+ :wait_readable, :wait_writeable
37
32
  end
38
33
  end
@@ -6,8 +6,7 @@ module Celluloid
6
6
  # More APIs and less monkeypatching would be useful here
7
7
  @messages = []
8
8
  @lock = Mutex.new
9
- @waker = Waker.new
10
- @reactor = Reactor.new(@waker)
9
+ @reactor = Reactor.new
11
10
  end
12
11
  end
13
12
  end
@@ -3,8 +3,13 @@ module Celluloid
3
3
  # React to incoming 0MQ and Celluloid events. This is kinda sorta supposed
4
4
  # to resemble the Reactor design pattern.
5
5
  class Reactor
6
- def initialize(waker)
7
- @waker = waker
6
+ extend Forwardable
7
+
8
+ def_delegator :@waker, :signal, :wakeup
9
+ def_delegator :@waker, :cleanup, :shutdown
10
+
11
+ def initialize
12
+ @waker = Waker.new
8
13
  @poller = ::ZMQ::Poller.new
9
14
  @readers = {}
10
15
  @writers = {}
@@ -30,13 +35,12 @@ module Celluloid
30
35
  if set.has_key? socket
31
36
  raise ArgumentError, "another method is already waiting on #{socket.inspect}"
32
37
  else
33
- set[socket] = Fiber.current
38
+ set[socket] = Task.current
34
39
  end
35
40
 
36
41
  @poller.register socket, type
37
- Fiber.yield
38
42
 
39
- @poller.deregister socket, type
43
+ Task.suspend :zmqwait
40
44
  socket
41
45
  end
42
46
 
@@ -57,16 +61,28 @@ module Celluloid
57
61
 
58
62
  @poller.readables.each do |sock|
59
63
  if sock == @waker.socket
60
- yield
64
+ @waker.wait
61
65
  else
62
- fiber = @readers.delete sock
63
- fiber.resume if fiber
66
+ task = @readers.delete sock
67
+ @poller.deregister sock, ::ZMQ::POLLIN
68
+
69
+ if task
70
+ task.resume
71
+ else
72
+ Celluloid::Logger.debug "ZMQ error: got read event without associated reader"
73
+ end
64
74
  end
65
75
  end
66
76
 
67
77
  @poller.writables.each do |sock|
68
- fiber = @writers.delete sock
69
- fiber.resume if fiber
78
+ task = @writers.delete sock
79
+ @poller.deregister sock, ::ZMQ::POLLOUT
80
+
81
+ if task
82
+ task.resume
83
+ else
84
+ Celluloid::Logger.debug "ZMQ error: got write event without associated reader"
85
+ end
70
86
  end
71
87
  end
72
88
  end
@@ -1,5 +1,5 @@
1
1
  module Celluloid
2
2
  module ZMQ
3
- VERSION = "0.7.1"
3
+ VERSION = "0.8.0"
4
4
  end
5
5
  end
@@ -1,6 +1,7 @@
1
1
  module Celluloid
2
2
  module ZMQ
3
- class DeadWakerError < Celluloid::IO::DeadWakerError; end # You can't wake the dead
3
+ # You can't wake the dead
4
+ DeadWakerError = Class.new IOError
4
5
 
5
6
  # Wakes up sleepy threads so that they can check their mailbox
6
7
  # Works like a ConditionVariable, except it's implemented as a ZMQ socket
@@ -16,12 +16,12 @@ Gem::Specification.new do |gem|
16
16
  gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
17
  gem.require_paths = ["lib"]
18
18
 
19
- gem.add_dependency "celluloid", ">= 0.7.0"
20
- gem.add_dependency "celluloid-zmq", ">= 0.7.0"
19
+ gem.add_dependency "celluloid", "~> 0.8.0"
20
+ gem.add_dependency "celluloid-zmq", "~> 0.8.0"
21
21
  gem.add_dependency "redis"
22
22
  gem.add_dependency "redis-namespace"
23
23
 
24
24
  gem.add_development_dependency "rake"
25
- gem.add_development_dependency "rspec", ">= 2.7.0"
25
+ gem.add_development_dependency "rspec", "~> 2.7.0"
26
26
  #gem.add_development_dependency "zk"
27
27
  end
@@ -10,16 +10,17 @@ require 'dcell/node'
10
10
  require 'dcell/global'
11
11
  require 'dcell/responses'
12
12
  require 'dcell/router'
13
+ require 'dcell/rpc'
13
14
  require 'dcell/server'
14
15
 
15
16
  require 'dcell/registries/redis_adapter'
16
- require 'dcell/application'
17
17
  require 'dcell/celluloid_ext'
18
18
 
19
19
  # Distributed Celluloid
20
20
  module DCell
21
21
  DEFAULT_PORT = 7777 # Default DCell port
22
22
  ZMQ_POOL_SIZE = 1 # DCell uses a fixed-size 0MQ thread pool
23
+
23
24
  @zmq_context = Celluloid::ZMQ.context = ::ZMQ::Context.new(ZMQ_POOL_SIZE)
24
25
  @config_lock = Mutex.new
25
26
 
@@ -78,12 +79,12 @@ module DCell
78
79
 
79
80
  # Run the DCell application
80
81
  def run
81
- DCell::Application.run
82
+ DCell::Group.run
82
83
  end
83
84
 
84
85
  # Run the DCell application in the background
85
86
  def run!
86
- DCell::Application.run!
87
+ DCell::Group.run!
87
88
  end
88
89
 
89
90
  # Start combines setup and run! into a single step
@@ -92,4 +93,9 @@ module DCell
92
93
  run!
93
94
  end
94
95
  end
96
+
97
+ # DCell's actor dependencies
98
+ class Group < Celluloid::Group
99
+ supervise Server, :as => :dcell_server
100
+ end
95
101
  end
@@ -54,4 +54,16 @@ module Celluloid
54
54
  DCell::MailboxProxy._load(string)
55
55
  end
56
56
  end
57
+
58
+ class SyncCall
59
+ def _dump(level)
60
+ rpc_id = DCell::RPC::Manager.register self
61
+ payload = Marshal.dump([@caller,@method,@arguments,@block])
62
+ "#{rpc_id.to_s(16)}@#{DCell.id}:#{payload}"
63
+ end
64
+
65
+ def self._load(string)
66
+ DCell::RPC._load(string)
67
+ end
68
+ end
57
69
  end
@@ -1,6 +1,7 @@
1
1
  module DCell
2
2
  # A node in a DCell cluster
3
3
  class Node
4
+ include Celluloid
4
5
  include Celluloid::FSM
5
6
  attr_reader :id, :addr
6
7
 
@@ -69,6 +70,9 @@ module DCell
69
70
  @id, @addr = id, addr
70
71
  @socket = nil
71
72
  @heartbeat = nil
73
+
74
+ # Total hax to accommodate the new Celluloid::FSM API
75
+ attach self
72
76
  end
73
77
 
74
78
  def finalize
@@ -59,7 +59,7 @@ module DCell
59
59
 
60
60
  def get(key)
61
61
  string = @redis.hget 'globals', key.to_s
62
- Marshal.load string
62
+ Marshal.load string if string
63
63
  end
64
64
 
65
65
  # Set a global value
@@ -0,0 +1,66 @@
1
+ require 'weakref'
2
+
3
+ module DCell
4
+ EPOCH = Time.new(2012, 1, 1, 0, 0, 0, "+00:00") # All things begin in 2012
5
+
6
+ class RPC < Celluloid::SyncCall
7
+ def initialize(id, caller, method, arguments, block)
8
+ @id, @caller, @method, @arguments, @block = id, caller, method, arguments, block
9
+ end
10
+
11
+ # Custom marshaller for compatibility with Celluloid::Mailbox marshalling
12
+ def _dump(level)
13
+ payload = Marshal.dump [@caller, @method, @arguments, @block]
14
+ "#{@id}:#{payload}"
15
+ end
16
+
17
+ # Loader for custom marshal format
18
+ def self._load(string)
19
+ id = string.slice!(0, string.index(":") + 1)
20
+ match = id.match(/^([0-9a-fA-F]+)@(.+?):$/)
21
+ raise ArgumentError, "couldn't parse call ID" unless match
22
+
23
+ call_id, node_id = match[1], match[2]
24
+
25
+ if DCell.id == node_id
26
+ Manager.claim Integer("0x#{call_id}")
27
+ else
28
+ caller, method, arguments, block = Marshal.load(string)
29
+ RPC.new("#{call_id}@#{node_id}", caller, method, arguments, block)
30
+ end
31
+ end
32
+
33
+ # Tracks calls-in-flight
34
+ class Manager
35
+ @mutex = Mutex.new
36
+ @ids = {}
37
+ @calls = {}
38
+ @serial = Integer(Time.now - EPOCH) * 0x100000
39
+
40
+ def self.register(call)
41
+ @mutex.lock
42
+ call_id = @ids[call.object_id]
43
+ unless call_id
44
+ call_id = @serial
45
+ @serial += 1
46
+ @ids[call.object_id] = call_id
47
+ end
48
+
49
+ @calls[call_id] = WeakRef.new(call)
50
+ call_id
51
+ ensure
52
+ @mutex.unlock
53
+ end
54
+
55
+ def self.claim(call_id)
56
+ @mutex.lock
57
+ ref = @calls.delete(call_id)
58
+ ref.__getobj__ if ref
59
+ rescue WeakRef::RefError
60
+ # Nothing to see here, folks
61
+ ensure
62
+ @mutex.unlock
63
+ end
64
+ end
65
+ end
66
+ end
@@ -1,3 +1,3 @@
1
1
  module DCell
2
- VERSION = "0.7.1"
2
+ VERSION = "0.8.0"
3
3
  end
@@ -1,6 +1,10 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe DCell::Global do
4
+ it "can handle unexisting keys" do
5
+ expect { DCell::Global[:unexisting] }.to_not raise_exception
6
+ end
7
+
4
8
  it "stores values" do
5
9
  DCell::Global[:the_answer] = 42
6
10
  DCell::Global[:the_answer].should == 42
@@ -25,9 +25,9 @@ class TestActor
25
25
  end
26
26
  end
27
27
 
28
- class TestApplication < Celluloid::Application
29
- supervise DCell::Application
28
+ class TestGroup < Celluloid::Group
29
+ supervise DCell::Group
30
30
  supervise TestActor, :as => :test_actor
31
31
  end
32
32
 
33
- TestApplication.run
33
+ TestGroup.run
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dcell
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.8.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,33 +9,33 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-06 00:00:00.000000000 Z
12
+ date: 2012-01-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: celluloid
16
- requirement: &70286435226960 !ruby/object:Gem::Requirement
16
+ requirement: &70247796045460 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ! '>='
19
+ - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 0.7.0
21
+ version: 0.8.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70286435226960
24
+ version_requirements: *70247796045460
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: celluloid-zmq
27
- requirement: &70286435226380 !ruby/object:Gem::Requirement
27
+ requirement: &70247796044740 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
- - - ! '>='
30
+ - - ~>
31
31
  - !ruby/object:Gem::Version
32
- version: 0.7.0
32
+ version: 0.8.0
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70286435226380
35
+ version_requirements: *70247796044740
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: redis
38
- requirement: &70286435225840 !ruby/object:Gem::Requirement
38
+ requirement: &70247796043700 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70286435225840
46
+ version_requirements: *70247796043700
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: redis-namespace
49
- requirement: &70286435225200 !ruby/object:Gem::Requirement
49
+ requirement: &70247796043240 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70286435225200
57
+ version_requirements: *70247796043240
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rake
60
- requirement: &70286435224680 !ruby/object:Gem::Requirement
60
+ requirement: &70247796042780 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,18 +65,18 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70286435224680
68
+ version_requirements: *70247796042780
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
- requirement: &70286435223880 !ruby/object:Gem::Requirement
71
+ requirement: &70247796042200 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
- - - ! '>='
74
+ - - ~>
75
75
  - !ruby/object:Gem::Version
76
76
  version: 2.7.0
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70286435223880
79
+ version_requirements: *70247796042200
80
80
  description: DCell is an distributed object framework based on Celluloid built on
81
81
  0MQ and Zookeeper
82
82
  email:
@@ -87,6 +87,7 @@ extra_rdoc_files: []
87
87
  files:
88
88
  - .gitignore
89
89
  - .rspec
90
+ - .travis.yml
90
91
  - CHANGES.md
91
92
  - Gemfile
92
93
  - LICENSE.txt
@@ -112,7 +113,6 @@ files:
112
113
  - dcell.gemspec
113
114
  - lib/dcell.rb
114
115
  - lib/dcell/actor_proxy.rb
115
- - lib/dcell/application.rb
116
116
  - lib/dcell/celluloid_ext.rb
117
117
  - lib/dcell/directory.rb
118
118
  - lib/dcell/global.rb
@@ -123,6 +123,7 @@ files:
123
123
  - lib/dcell/registries/zk_adapter.rb
124
124
  - lib/dcell/responses.rb
125
125
  - lib/dcell/router.rb
126
+ - lib/dcell/rpc.rb
126
127
  - lib/dcell/rspec.rb
127
128
  - lib/dcell/server.rb
128
129
  - lib/dcell/version.rb
@@ -1,6 +0,0 @@
1
- module DCell
2
- # Actors which run when DCell is active
3
- class Application < Celluloid::Application
4
- supervise Server, :as => :dcell_server
5
- end
6
- end