sumac 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/README.md +2 -0
  4. data/lib/core_extensions.rb +207 -0
  5. data/lib/sumac.rb +94 -0
  6. data/lib/sumac/adapter.rb +5 -0
  7. data/lib/sumac/adapter/closed.rb +7 -0
  8. data/lib/sumac/argument_error.rb +5 -0
  9. data/lib/sumac/call_dispatcher.rb +70 -0
  10. data/lib/sumac/call_processor.rb +93 -0
  11. data/lib/sumac/closed_error.rb +5 -0
  12. data/lib/sumac/closer.rb +53 -0
  13. data/lib/sumac/connection.rb +94 -0
  14. data/lib/sumac/exposed_object.rb +131 -0
  15. data/lib/sumac/exposed_object_child.rb +158 -0
  16. data/lib/sumac/forgoten.rb +5 -0
  17. data/lib/sumac/handshake.rb +48 -0
  18. data/lib/sumac/id_allocator.rb +99 -0
  19. data/lib/sumac/local_reference.rb +16 -0
  20. data/lib/sumac/local_references.rb +80 -0
  21. data/lib/sumac/message.rb +19 -0
  22. data/lib/sumac/message/exchange.rb +30 -0
  23. data/lib/sumac/message/exchange/base.rb +15 -0
  24. data/lib/sumac/message/exchange/call_request.rb +96 -0
  25. data/lib/sumac/message/exchange/call_response.rb +83 -0
  26. data/lib/sumac/message/exchange/compatibility_notification.rb +53 -0
  27. data/lib/sumac/message/exchange/forget_notification.rb +77 -0
  28. data/lib/sumac/message/exchange/id.rb +30 -0
  29. data/lib/sumac/message/exchange/initialization_notification.rb +52 -0
  30. data/lib/sumac/message/exchange/notification.rb +9 -0
  31. data/lib/sumac/message/exchange/shutdown_notification.rb +27 -0
  32. data/lib/sumac/message/object.rb +72 -0
  33. data/lib/sumac/message/object/array.rb +57 -0
  34. data/lib/sumac/message/object/base.rb +21 -0
  35. data/lib/sumac/message/object/boolean.rb +45 -0
  36. data/lib/sumac/message/object/exception.rb +66 -0
  37. data/lib/sumac/message/object/exposed.rb +79 -0
  38. data/lib/sumac/message/object/exposed_child.rb +86 -0
  39. data/lib/sumac/message/object/float.rb +45 -0
  40. data/lib/sumac/message/object/hash_table.rb +75 -0
  41. data/lib/sumac/message/object/integer.rb +45 -0
  42. data/lib/sumac/message/object/native_exception.rb +56 -0
  43. data/lib/sumac/message/object/null.rb +44 -0
  44. data/lib/sumac/message/object/string.rb +45 -0
  45. data/lib/sumac/message_error.rb +5 -0
  46. data/lib/sumac/messenger.rb +65 -0
  47. data/lib/sumac/native_error.rb +17 -0
  48. data/lib/sumac/no_method_error.rb +9 -0
  49. data/lib/sumac/reference.rb +68 -0
  50. data/lib/sumac/remote_entry.rb +42 -0
  51. data/lib/sumac/remote_object.rb +39 -0
  52. data/lib/sumac/remote_object_child.rb +38 -0
  53. data/lib/sumac/remote_reference.rb +16 -0
  54. data/lib/sumac/remote_references.rb +70 -0
  55. data/lib/sumac/scheduler.rb +56 -0
  56. data/lib/sumac/shutdown.rb +32 -0
  57. data/lib/sumac/stale_object_error.rb +5 -0
  58. data/lib/sumac/unexposable_object_error.rb +9 -0
  59. data/lib/sumac/worker_pool.rb +35 -0
  60. data/test/test_id_allocator.rb +25 -0
  61. metadata +145 -0
@@ -0,0 +1,39 @@
1
+ class Sumac
2
+ class RemoteObject < Object
3
+
4
+ def initialize(connection, remote_reference)
5
+ raise "argument 'connection' must be a Connection" unless connection.is_a?(Connection)
6
+ @connection = connection
7
+ raise unless remote_reference.is_a?(RemoteReference)
8
+ @remote_reference = remote_reference
9
+ end
10
+
11
+ def method_missing(method_name, *arguments, &block) # blocks not working yet
12
+ @connection.mutex.lock
13
+ raise StaleObjectError unless @remote_reference.callable?
14
+ begin
15
+ arguments << block.to_lambda if block_given?
16
+ return_value = @connection.call_dispatcher.make_call(self, method_name.to_s, arguments)
17
+ rescue ClosedError
18
+ raise StaleObjectError
19
+ end
20
+ return_value
21
+ ensure
22
+ @connection.mutex.unlock if @connection.mutex.owned?
23
+ end
24
+
25
+ def __remote_reference__
26
+ @remote_reference
27
+ end
28
+
29
+ def forget
30
+ @connection.mutex.synchronize { @remote_reference.local_forget_request }
31
+ nil
32
+ end
33
+
34
+ def inspect
35
+ "#<Sumac::RemoteObject:#{"0x00%x" % (object_id << 1)}>"
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,38 @@
1
+ class Sumac
2
+ class RemoteObjectChild < Object
3
+
4
+ def initialize(connection, parent, key)
5
+ raise "argument 'connection' must be a Connection" unless connection.is_a?(Connection)
6
+ @connection = connection
7
+ raise unless parent.is_a?(RemoteObject)
8
+ @parent = parent
9
+ @key = key
10
+ end
11
+
12
+ def method_missing(method_name, *arguments, &block) # blocks not working yet
13
+ @connection.mutex.lock
14
+ begin
15
+ arguments << block.to_lambda if block_given?
16
+ return_value = @connection.call_dispatcher.make_call(self, method_name.to_s, arguments)
17
+ rescue ClosedError
18
+ raise StaleObjectError
19
+ end
20
+ return_value
21
+ ensure
22
+ @connection.mutex.unlock if @connection.mutex.owned?
23
+ end
24
+
25
+ def __key__
26
+ @key
27
+ end
28
+
29
+ def __parent__
30
+ @parent
31
+ end
32
+
33
+ def inspect
34
+ "#<Sumac::RemoteObjectChild:#{"0x00%x" % (object_id << 1)}>"
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,16 @@
1
+ class Sumac
2
+ class RemoteReference < Reference
3
+
4
+ attr_reader :remote_object
5
+
6
+ def initialize(connection, exposed_id)
7
+ super(connection, exposed_id)
8
+ @remote_object = RemoteObject.new(@connection, self)
9
+ end
10
+
11
+ def remove
12
+ @connection.remote_references.remove(self)
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,70 @@
1
+ class Sumac
2
+ class RemoteReferences
3
+
4
+ def initialize(connection)
5
+ raise "argument 'connection' must be a Connection" unless connection.is_a?(Connection)
6
+ @connection = connection
7
+ @exposed_id_table = {}
8
+ @transaction = []
9
+ end
10
+
11
+ def detach
12
+ each { |reference| reference.detach }
13
+ end
14
+
15
+ def destroy
16
+ each { |reference| reference.destroy }
17
+ end
18
+
19
+ def from_id(exposed_id)
20
+ raise unless IDAllocator.valid?(exposed_id)
21
+ reference = find(exposed_id) || create(exposed_id)
22
+ end
23
+
24
+ def from_object(remote_object)
25
+ raise unless remote_object.is_a?(RemoteObject)
26
+ reference = remote_object.__remote_reference__
27
+ raise StaleObjectError unless reference.callable?
28
+ reference
29
+ end
30
+
31
+ def remove(reference)
32
+ @exposed_id_table.delete(reference.exposed_id)
33
+ end
34
+
35
+ def rollback_transaction
36
+ @transaction.each { |reference| reference.quiet_forget }
37
+ @transaction = []
38
+ end
39
+
40
+ def commit_transaction
41
+ @transaction = nil
42
+ end
43
+
44
+ def start_transaction
45
+ @transaction = []
46
+ end
47
+
48
+ private
49
+
50
+ def create(new_exposed_id)
51
+ new_reference = RemoteReference.new(@connection, new_exposed_id)
52
+ @exposed_id_table[new_exposed_id] = new_reference
53
+ @transaction << new_reference if @transaction
54
+ new_reference
55
+ end
56
+
57
+ def find(exposed_id)
58
+ reference = @exposed_id_table[exposed_id]
59
+ return if reference && reference.stale?
60
+ reference
61
+ end
62
+
63
+ def each
64
+ @exposed_id_table.values.each do |reference|
65
+ yield(reference) unless reference.stale?
66
+ end
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,56 @@
1
+ class Sumac
2
+ class Scheduler
3
+
4
+ def initialize(connection, worker_count)
5
+ raise "argument 'connection' must be a Connection" unless connection.is_a?(Connection)
6
+ @connection = connection
7
+ @worker_pool = WorkerPool.new(worker_count)
8
+ @dispatch_worker = nil
9
+ end
10
+
11
+ def run
12
+ @dispatch_worker = Thread.new do
13
+ @connection.mutex.synchronize do
14
+ raise unless @connection.at?(:initial)
15
+ @connection.to(:compatibility_handshake)
16
+ end
17
+ receiver_loop
18
+ end
19
+ nil
20
+ end
21
+
22
+ def receiver_loop
23
+ loop do
24
+ begin
25
+ message_string = @connection.messenger_adapter.receive
26
+ rescue Adapter::ClosedError
27
+ @connection.mutex.synchronize do
28
+ unless @connection.at?([:kill, :close])
29
+ @connection.to(:kill)
30
+ end
31
+ end
32
+ end
33
+ break if @connection.mutex.synchronize { @connection.at?([:kill, :close]) }
34
+ dispatch(message_string)
35
+ end
36
+ nil
37
+ end
38
+
39
+ def dispatch(message_string)
40
+ #@worker_pool.run do
41
+ @connection.mutex.synchronize do
42
+ break if @connection.at?([:kill, :close])
43
+ @connection.messenger.receive(message_string)
44
+ end
45
+ #end
46
+ nil
47
+ end
48
+
49
+ def join
50
+ @dispatch_worker.join
51
+ @worker_pool.join
52
+ nil
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,32 @@
1
+ class Sumac
2
+ class Shutdown
3
+
4
+ def initialize(connection)
5
+ raise "argument 'connection' must be a Connection" unless connection.is_a?(Connection)
6
+ @connection = connection
7
+ end
8
+
9
+ #def initiate
10
+ #raise unless @orchestrator.state_machine.at?(:active)
11
+ #@orchestrator.state_machine.to(:initiate_shutdown)
12
+ #nil
13
+ #end
14
+
15
+ #def initiated?
16
+ #@orchestrator.state_machine.at?([:initiate_shutdown, :shutdown, :close])
17
+ #end
18
+
19
+ def send_notification
20
+ message = Message::Exchange::ShutdownNotification.new(@connection)
21
+ @connection.messenger.send(message)
22
+ nil
23
+ end
24
+
25
+ def receive(exchange)
26
+ raise MessageError unless exchange.is_a?(Message::Exchange::ShutdownNotification)
27
+ @connection.to(:shutdown)
28
+ nil
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,5 @@
1
+ class Sumac
2
+ class StaleObjectError < StandardError
3
+
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ class Sumac
2
+ class UnexposableObjectError < MessageError
3
+
4
+ def message
5
+ "object has not been exposed, it can not be shared"
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,35 @@
1
+ class Sumac
2
+ class WorkerPool
3
+
4
+ def initialize(size = 1, duck_types: {})
5
+ raise 'Error: worker count invalid' if size < 1
6
+ @thread_class = duck_types[:thread] || Thread
7
+ @semaphore = QuackConcurrency::Semaphore.new(size)
8
+ @threads = []
9
+ end
10
+
11
+ def size
12
+ @semaphore.permit_count
13
+ end
14
+
15
+ def size=(new_size)
16
+ @semaphore.set_permit_count!(new_size)
17
+ end
18
+
19
+ def run(&block)
20
+ @semaphore.acquire
21
+ @threads << @thread_class.new do
22
+ block.call
23
+ @threads.delete(@thread_class.current)
24
+ @semaphore.release
25
+ end
26
+ nil
27
+ end
28
+
29
+ def join
30
+ @threads.each(&:join)
31
+ nil
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,25 @@
1
+ class TestIDAllocator < Test::Unit::TestCase
2
+
3
+
4
+ def setup
5
+
6
+ end
7
+
8
+
9
+ def teardown
10
+ ## Nothing really
11
+ end
12
+
13
+
14
+ def test
15
+ allocator = Sumac::IDAllocator.new
16
+ assert_equal(allocator.allocate, 0)
17
+ assert_equal(allocator.allocate, 1)
18
+ assert_equal(allocator.allocate(5), 5)
19
+ #assert_not_equal(allocator.allocate(0), 0)
20
+ assert_equal(allocator.free(0), nil)
21
+ assert_equal(allocator.allocate, 0)
22
+ end
23
+
24
+
25
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sumac
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Rob Fors
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-02-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: emittable
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.0.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.0.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: quack_concurrency
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.0.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 0.0.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: queued_state_machine
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 0.0.1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 0.0.1
55
+ description: Eases implementation of computer to computer communication by enabling
56
+ programs to pass objects between each other.
57
+ email: mail@robfors.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - LICENSE
63
+ - README.md
64
+ - lib/core_extensions.rb
65
+ - lib/sumac.rb
66
+ - lib/sumac/adapter.rb
67
+ - lib/sumac/adapter/closed.rb
68
+ - lib/sumac/argument_error.rb
69
+ - lib/sumac/call_dispatcher.rb
70
+ - lib/sumac/call_processor.rb
71
+ - lib/sumac/closed_error.rb
72
+ - lib/sumac/closer.rb
73
+ - lib/sumac/connection.rb
74
+ - lib/sumac/exposed_object.rb
75
+ - lib/sumac/exposed_object_child.rb
76
+ - lib/sumac/forgoten.rb
77
+ - lib/sumac/handshake.rb
78
+ - lib/sumac/id_allocator.rb
79
+ - lib/sumac/local_reference.rb
80
+ - lib/sumac/local_references.rb
81
+ - lib/sumac/message.rb
82
+ - lib/sumac/message/exchange.rb
83
+ - lib/sumac/message/exchange/base.rb
84
+ - lib/sumac/message/exchange/call_request.rb
85
+ - lib/sumac/message/exchange/call_response.rb
86
+ - lib/sumac/message/exchange/compatibility_notification.rb
87
+ - lib/sumac/message/exchange/forget_notification.rb
88
+ - lib/sumac/message/exchange/id.rb
89
+ - lib/sumac/message/exchange/initialization_notification.rb
90
+ - lib/sumac/message/exchange/notification.rb
91
+ - lib/sumac/message/exchange/shutdown_notification.rb
92
+ - lib/sumac/message/object.rb
93
+ - lib/sumac/message/object/array.rb
94
+ - lib/sumac/message/object/base.rb
95
+ - lib/sumac/message/object/boolean.rb
96
+ - lib/sumac/message/object/exception.rb
97
+ - lib/sumac/message/object/exposed.rb
98
+ - lib/sumac/message/object/exposed_child.rb
99
+ - lib/sumac/message/object/float.rb
100
+ - lib/sumac/message/object/hash_table.rb
101
+ - lib/sumac/message/object/integer.rb
102
+ - lib/sumac/message/object/native_exception.rb
103
+ - lib/sumac/message/object/null.rb
104
+ - lib/sumac/message/object/string.rb
105
+ - lib/sumac/message_error.rb
106
+ - lib/sumac/messenger.rb
107
+ - lib/sumac/native_error.rb
108
+ - lib/sumac/no_method_error.rb
109
+ - lib/sumac/reference.rb
110
+ - lib/sumac/remote_entry.rb
111
+ - lib/sumac/remote_object.rb
112
+ - lib/sumac/remote_object_child.rb
113
+ - lib/sumac/remote_reference.rb
114
+ - lib/sumac/remote_references.rb
115
+ - lib/sumac/scheduler.rb
116
+ - lib/sumac/shutdown.rb
117
+ - lib/sumac/stale_object_error.rb
118
+ - lib/sumac/unexposable_object_error.rb
119
+ - lib/sumac/worker_pool.rb
120
+ - test/test_id_allocator.rb
121
+ homepage: https://github.com/robfors/ruby-sumac
122
+ licenses:
123
+ - Apache-2.0
124
+ metadata: {}
125
+ post_install_message:
126
+ rdoc_options: []
127
+ require_paths:
128
+ - lib
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ requirements: []
140
+ rubyforge_project:
141
+ rubygems_version: 2.4.8
142
+ signing_key:
143
+ specification_version: 4
144
+ summary: Object based communication protocol.
145
+ test_files: []