hakuban 0.5.0 → 0.6.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 79db90522bce42223139845bf81169a9e75a2997a90e71952b0b00d852272ff6
4
- data.tar.gz: 35d50834b1a5a2626e9e3ad62c063b04acfc86569f887e57afe2578125d994cc
3
+ metadata.gz: 80450f20193ebd24bb8f0b55e9e822be3a0271d26aa1c41954fe09a23c02a62d
4
+ data.tar.gz: 56a74e6c21534550ef484ae58ede825fd6690f847d45245c57be3271943d77bb
5
5
  SHA512:
6
- metadata.gz: 5d74f9761c28495c9d6caed241fb907147aff987d8c9d5526ded5d15f6e43ac781354baae9894fc74684ecad374646d8fde4cf90b26550a2e954f6bbf95f5ecb
7
- data.tar.gz: 2c48edc2b71800bf19e3a1f267de234493e1e54aa6ae6fb4042ba1fc79f22a35aa28015e2d0b37f6ddb5c491817cf6698330b609dba96077e6d26ddcd441cb28
6
+ metadata.gz: 9a67bad1007498001d0550abd1eab1827d155fe6b6f25ee94aa08149bd054090bc9d0b37e1767eb03b7b7971216643e4c7dd396f7ef7cc20420ea7b54fbebdea
7
+ data.tar.gz: 5f3d377665666e3cada421c1140c3a8e8b00e84564b61a6c29991560b45615846dfbddce318b212b2d386d9f3b84737b59a7fccc5c4068661da1b366032b8c6d
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2015-2021 yunta
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,56 @@
1
+ #!/bin/env ruby
2
+
3
+ require 'slop'
4
+ require 'pp'
5
+ require 'hakuban/async'
6
+
7
+
8
+ OPTIONS = Slop.parse { |o|
9
+ o.string '-c', '--connect', "Hakuban upstream address (default: ws://127.0.0.1:3001)", default: "ws://127.0.0.1:3001"
10
+ o.string '-o', '--object', "Object descriptor"
11
+ o.array '-t', '--tag', "Tag descriptor(s)"
12
+ o.bool '-d', '--debug', 'Show debug messages'
13
+ o.on '-h', '--help' do puts o; exit end
14
+ }
15
+
16
+ Hakuban.logger_initialize("hakuban=debug") if OPTIONS.debug?
17
+ hakuban = Hakuban::LocalNode.new(name: OPTIONS["name"])
18
+ connector = Hakuban::WebsocketConnector.new(hakuban, OPTIONS["connect"])
19
+
20
+ observe_contract = if OPTIONS["object"]
21
+ json = JSON.load(OPTIONS["object"])
22
+ tags = OPTIONS["tag"].map { |tag| JSON.load(tag) }
23
+ hakuban.object(tags, json).observe
24
+ else
25
+ tag = OPTIONS["tag"].map { |tag| JSON.load(tag) }
26
+ hakuban.tag(tag[0]).observe
27
+ end
28
+
29
+
30
+ def print_event(descriptor, event)
31
+ puts "-"*120
32
+ puts "Event: " + event
33
+ puts "Descriptor: "
34
+ descriptor.tags.each { |tag|
35
+ puts "\tTags: " + JSON.dump(tag.json)
36
+ }
37
+ puts "\tJSON: " + JSON.dump(descriptor.json)
38
+ end
39
+
40
+ Async {
41
+
42
+ observe_contract.async { |object|
43
+ print_event(object.descriptor, "create")
44
+ while object.next_change
45
+ print_event(object.descriptor, "change")
46
+ if state = object.state
47
+ puts "Version: " + state.version.inspect
48
+ puts "Last synchronized: " + state.synchronized.to_s + "ms ago"
49
+ puts "Data:\n"
50
+ pp state.data
51
+ end
52
+ end
53
+ print_event(object.descriptor, "drop")
54
+ }
55
+
56
+ }
@@ -0,0 +1,45 @@
1
+ #!/bin/env ruby
2
+
3
+ require 'slop'
4
+ require 'hakuban/thread'
5
+ require 'socket'
6
+
7
+ STDOUT.sync = true
8
+
9
+
10
+ OPTIONS = Slop.parse { |o|
11
+ o.string '-c', '--connect', "Hakuban upstream address (default: ws://127.0.0.1:3001)", default: "ws://127.0.0.1:3001"
12
+ o.string '-n', '--name', "Node name (default: engine-PID)", default: "engine##{$$}@#{Socket.gethostname}"
13
+ o.array '-e', '--engines', "engines to start, a glob pattern matched against class name (default: *)", delimiter: ",", default: ["*"]
14
+ o.bool '-d', '--debug', 'Show debug messages'
15
+ o.on '-h', '--help' do puts o; exit end
16
+ }
17
+
18
+
19
+ Hakuban.logger_initialize("hakuban=debug") if OPTIONS.debug?
20
+ $hakuban = Hakuban::LocalNode.new(name: OPTIONS["name"])
21
+ connector = Hakuban::WebsocketConnector.new($hakuban, OPTIONS["connect"])
22
+
23
+
24
+ OPTIONS.arguments.each { |to_require|
25
+ require to_require
26
+ }
27
+
28
+ started_engines = OPTIONS[:engines].map { |engine_name_pattern|
29
+ Hakuban::Engine.engines.select { |engine_class|
30
+ File.fnmatch(engine_name_pattern, engine_class.name)
31
+ }
32
+ }.flatten.uniq.map { |engine_class|
33
+ engine_class.new
34
+ }.each { |engine|
35
+ engine.start($hakuban)
36
+ puts "Started engine: #{engine.class.name}"
37
+ }
38
+
39
+ sleep
40
+
41
+ started_engines.each { |engine|
42
+ engine.stop
43
+ puts "Stopped engine: #{engine.class.name}"
44
+ }
45
+
@@ -0,0 +1,45 @@
1
+ require 'hakuban'
2
+ require 'hakuban/manager'
3
+ require 'async'
4
+
5
+ module Hakuban
6
+
7
+ class AsyncObjectManager < ObjectManager
8
+ def async_run
9
+ Async { yield }
10
+ end
11
+
12
+ def async_join(async)
13
+ async.wait
14
+ end
15
+ end
16
+
17
+
18
+ class ObjectObserve
19
+ def async(&block)
20
+ AsyncObjectManager.new(self, ObservedObject, block)
21
+ end
22
+ end
23
+
24
+
25
+ class ObjectExpose
26
+ def async(&block)
27
+ AsyncObjectManager.new(self, ExposedObject, block)
28
+ end
29
+ end
30
+
31
+
32
+ class TagObserve
33
+ def async(&block)
34
+ AsyncObjectManager.new(self, ObservedObject, block)
35
+ end
36
+ end
37
+
38
+
39
+ class TagExpose
40
+ def async(&block)
41
+ AsyncObjectManager.new(self, ExposedObject, block)
42
+ end
43
+ end
44
+
45
+ end
@@ -0,0 +1,44 @@
1
+ module Hakuban
2
+
3
+ class Engine
4
+
5
+ def initialize
6
+ raise "Hakuban::Engine is abstract" if self.class == Hakuban::Engine
7
+ @contracts = []
8
+ end
9
+
10
+
11
+ def start(hakuban)
12
+ @contracts.concat([init(hakuban)])
13
+ @contracts.flatten!
14
+ @contracts.compact!
15
+ @contracts.uniq!
16
+ end
17
+
18
+ def init(hakuban)
19
+ raise "Hakuban::Engine::init is a pure virtual function, descendants should bring their own implementation"
20
+ end
21
+
22
+ def stop
23
+ @contracts.each { |contract|
24
+ contract.drop
25
+ }
26
+ end
27
+
28
+
29
+
30
+ @@descendants = []
31
+
32
+
33
+ def self.engines
34
+ @@descendants
35
+ end
36
+
37
+
38
+ def self.inherited(subclass)
39
+ @@descendants << subclass
40
+ end
41
+
42
+ end
43
+
44
+ end
data/lib/hakuban/ffi.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  require 'json'
2
2
  require 'ffi'
3
- require 'msgpack'
4
3
 
5
4
 
6
5
  # all functions which can trigger synchronuous callbacks, and those which wait on rust locks are "blocking: true" to avoid deadlock on GIL
@@ -26,12 +25,21 @@ module Hakuban::FFI
26
25
  layout :error, :uint8, :tag_expose_pointer, :pointer
27
26
  end
28
27
 
29
- class FFIObjectObserveState < FFI::Struct
30
- layout :synchronized, :uint8, :version_length, :size_t, :version, :pointer, :data_type_length, :size_t, :data_type, :pointer, :raw_length, :size_t, :raw, :pointer, :raw_arc, :pointer
28
+ class FFIObjectObserveStateGetVersionResult < FFI::Struct
29
+ layout :version_length, :size_t, :version_elements, :pointer
31
30
  end
32
-
31
+
32
+ class FFIObjectObserveStateGetDataTypeResult < FFI::Struct
33
+ layout :type_length, :size_t, :type_elements, :pointer
34
+ end
35
+
36
+ class FFIObjectObserveStateGetDataResult < FFI::Struct
37
+ layout :data_length, :size_t, :data_bytes, :pointer
38
+ end
39
+
33
40
  class FFIObjectExposeState < FFI::Struct
34
41
  layout :version_length, :size_t, :version, :pointer, :data_type_length, :size_t, :data_type, :pointer, :raw_length, :size_t, :raw, :pointer
42
+ attr_accessor :data_type_strings
35
43
 
36
44
  def self.construct(version, data_type, data)
37
45
  state = FFIObjectExposeState::new
@@ -40,7 +48,8 @@ module Hakuban::FFI
40
48
  state[:version].write_array_of_int64(version)
41
49
  state[:data_type_length] = data_type.size
42
50
  state[:data_type] = FFI::MemoryPointer.new(:pointer, data_type.size)
43
- state[:data_type].write_array_of_pointer(data_type.map {|string| FFI::MemoryPointer.from_string(string)})
51
+ state.data_type_strings = data_type.map {|string| FFI::MemoryPointer.from_string(string)}
52
+ state[:data_type].write_array_of_pointer(state.data_type_strings)
44
53
  state[:raw] = FFI::MemoryPointer.from_string(data)
45
54
  state[:raw_length] = data.size
46
55
  state
@@ -56,12 +65,13 @@ module Hakuban::FFI
56
65
  end
57
66
 
58
67
  class FFITagObserveObjectStateBorrowResult < FFI::Struct
59
- layout :error, :uint8, :state, FFIObjectObserveState.by_value
68
+ layout :error, :uint8, :state, :pointer
60
69
  end
61
70
 
62
71
  class FFIObjectDescriptor < FFI::Struct
63
72
  layout :tags_count, :size_t, :tags, :pointer, :json, :pointer
64
-
73
+ attr_accessor :tags_strings
74
+
65
75
  def tags
66
76
  self[:tags].read_array_of_pointer(self[:tags_count]).map { |string| JSON.parse(string.read_string()) } # does this copy the string?
67
77
  end
@@ -71,12 +81,11 @@ module Hakuban::FFI
71
81
  end
72
82
 
73
83
  def self.construct(tags,json)
74
- tags_strings = tags.map { |tag| JSON.dump(tag) }
75
- tags_strings_array = FFI::MemoryPointer.new(:pointer, tags_strings.size)
76
- tags_strings_array.write_array_of_pointer(tags_strings.map {|string| FFI::MemoryPointer.from_string(string)})
77
84
  descriptor = FFIObjectDescriptor.new
78
85
  descriptor[:tags_count] = tags.size
79
- descriptor[:tags] = tags_strings_array
86
+ descriptor.tags_strings = tags.map { |tag| FFI::MemoryPointer.from_string(JSON.dump(tag)) }
87
+ descriptor[:tags] = FFI::MemoryPointer.new(:pointer, descriptor.tags_strings.size)
88
+ descriptor[:tags].write_array_of_pointer(descriptor.tags_strings)
80
89
  descriptor[:json] = FFI::MemoryPointer.from_string(JSON.dump(json))
81
90
  descriptor
82
91
  end
@@ -116,37 +125,50 @@ module Hakuban::FFI
116
125
  #callback :tag_callback, [ :pointer, FFITagDescriptor.by_value, :uint8 ], :void
117
126
 
118
127
  attach_function :hakuban_local_node_new, [ :string ], FFILocalNodeNewResult.by_value
119
- attach_function :hakuban_local_node_drop, [ :pointer ], :void
128
+ attach_function :hakuban_local_node_drop, [ :pointer ], :void, blocking: true
120
129
 
121
130
  attach_function :hakuban_object_observe_new, [ :pointer, FFIObjectDescriptor.by_value ], FFIObjectObserveResult.by_value, blocking: true
122
131
  attach_function :hakuban_object_observe_drop, [ :pointer ], :void, blocking: true
123
- attach_function :hakuban_object_observe_state_borrow, [ :pointer ], FFIObjectObserveState.by_value, blocking: true
124
- attach_function :hakuban_object_observe_changes_callback_register, [ :pointer, :object_callback, :pointer ], :pointer, blocking: true
125
-
132
+ attach_function :hakuban_object_observe_state_borrow, [ :pointer ], :pointer, blocking: true
133
+ attach_function :hakuban_object_observe_events_get, [ :pointer ], :pointer, blocking: true
134
+
126
135
  attach_function :hakuban_object_expose_new, [ :pointer, FFIObjectDescriptor.by_value], FFIObjectExposeResult.by_value, blocking: true
127
136
  attach_function :hakuban_object_expose_drop, [ :pointer ], :void, blocking: true
128
- attach_function :hakuban_object_expose_state, [ :pointer, FFIObjectExposeState.by_value ], FFIObjectExposeStateResult.by_value, blocking: true
129
- attach_function :hakuban_object_expose_assigned, [ :pointer ], :uint8, blocking: true
130
- attach_function :hakuban_object_expose_changes_callback_register, [ :pointer, :object_callback, :pointer ], :pointer, blocking: true
137
+ attach_function :hakuban_object_expose_state, [ :pointer, FFIObjectExposeState.by_value, :uint64 ], FFIObjectExposeStateResult.by_value, blocking: true
138
+ attach_function :hakuban_object_expose_assignment, [ :pointer ], :uint64, blocking: true
139
+ attach_function :hakuban_object_expose_desynchronize, [ :pointer, :uint64 ], :void, blocking: true
140
+ attach_function :hakuban_object_expose_events_get, [ :pointer ], :pointer, blocking: true
131
141
 
132
142
  attach_function :hakuban_tag_observe_new, [ :pointer, FFITagDescriptor.by_value ], FFITagObserveResult.by_value, blocking: true
133
143
  attach_function :hakuban_tag_observe_drop, [ :pointer ], :void, blocking: true
134
144
  attach_function :hakuban_tag_observe_object_descriptors_borrow, [ :pointer ], FFIObjectDescriptors.by_value, blocking: true
135
145
  attach_function :hakuban_tag_observe_object_state_borrow, [ :pointer, FFIObjectDescriptor.by_value ], FFITagObserveObjectStateBorrowResult.by_value, blocking: true
136
- attach_function :hakuban_tag_observe_objects_changes_callback_register, [ :pointer, :object_callback, :pointer ], :pointer, blocking: true
146
+ attach_function :hakuban_tag_observe_events_get, [ :pointer ], :pointer, blocking: true
137
147
 
138
148
  attach_function :hakuban_tag_expose_new, [ :pointer, FFITagDescriptor.by_value ], FFITagExposeResult.by_value, blocking: true
139
149
  attach_function :hakuban_tag_expose_drop, [ :pointer ], :void, blocking: true
140
150
  attach_function :hakuban_tag_expose_object_descriptors_borrow, [ :pointer ], FFIObjectDescriptors.by_value, blocking: true
141
- attach_function :hakuban_tag_expose_object_state, [ :pointer, FFIObjectDescriptor.by_value, FFIObjectExposeState.by_value ], FFIObjectExposeStateResult.by_value, blocking: true
142
- attach_function :hakuban_tag_expose_objects_changes_callback_register, [ :pointer, :object_callback, :pointer ], :pointer, blocking: true
151
+ attach_function :hakuban_tag_expose_object_state, [ :pointer, FFIObjectDescriptor.by_value, FFIObjectExposeState.by_value, :uint64 ], FFIObjectExposeStateResult.by_value, blocking: true
152
+ attach_function :hakuban_tag_expose_object_assignment, [ :pointer, FFIObjectDescriptor.by_value ], :uint64, blocking: true
153
+ attach_function :hakuban_tag_expose_object_desynchronize, [ :pointer, FFIObjectDescriptor.by_value, :uint64 ], :void, blocking: true
154
+ attach_function :hakuban_tag_expose_events_get, [ :pointer ], :pointer, blocking: true
155
+
156
+ attach_function :hakuban_object_observe_state_get_synchronized, [ :pointer ], :uint64
157
+ attach_function :hakuban_object_observe_state_get_data_version, [ :pointer ], FFIObjectObserveStateGetVersionResult.by_value
158
+ attach_function :hakuban_object_observe_state_get_data_type, [ :pointer ], FFIObjectObserveStateGetDataTypeResult.by_value
159
+ attach_function :hakuban_object_observe_state_get_data, [ :pointer ], FFIObjectObserveStateGetDataResult.by_value
143
160
 
144
- attach_function :hakuban_object_observe_state_return, [ FFIObjectObserveState.by_value ], :void
161
+ attach_function :hakuban_object_descriptor_events_callback_register, [ :pointer, :object_callback, :pointer ], :pointer, blocking: true
162
+ attach_function :hakuban_object_descriptor_events_callback_unregister, [ :pointer ], :void, blocking: true
163
+ attach_function :hakuban_object_descriptor_events_return, [ :pointer ], :void, blocking: true
164
+
165
+ attach_function :hakuban_object_observe_state_return, [ :pointer ], :void
145
166
  attach_function :hakuban_object_descriptors_return, [ FFIObjectDescriptors.by_value ], :void
146
- attach_function :hakuban_object_callback_unregister, [ :pointer ], :void, blocking: true
147
167
 
148
168
  attach_function :hakuban_tokio_init_multi_thread, [ :size_t ], :pointer
149
- attach_function :hakuban_tokio_websocket_connector_new, [ :pointer, :string ], FFITokioWebsocketConnectorNewResult.by_value
150
- attach_function :hakuban_tokio_websocket_connector_start, [ :pointer, :pointer, :pointer ], :void
169
+ attach_function :hakuban_tokio_websocket_connector_new, [ :pointer, :pointer, :string ], FFITokioWebsocketConnectorNewResult.by_value
170
+ attach_function :hakuban_tokio_websocket_connector_drop, [ :pointer, :pointer ], :void, blocking: true
171
+
172
+ attach_function :hakuban_logger_initialize, [ :string ], :uint8
151
173
 
152
174
  end