hakuban 0.5.2 → 0.6.2

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: 79890c306cc3df4c9d3382773a66d38fa6373c6f1c2c874301ba0409050ab20d
4
- data.tar.gz: e17ffc0520c6605a3cb2b207de58fc98c19d3c8d2472adf681a99dcbcb48b450
3
+ metadata.gz: 6d0b0d54e3b6dce8ecd11b991e94768247f2e978cca397d430fcab6bfd987484
4
+ data.tar.gz: 81466178ba54513cb665cd49800599125bda1ba108f7eee71efff3e5b496cbb5
5
5
  SHA512:
6
- metadata.gz: a243af479fa4f47245696cb408498ce37fb46c4ca03563fc7b648dbec40cc0a18c76d227358f1dc36a1c66c31f102dc042fcf162168210b8d87f863230f4bf3f
7
- data.tar.gz: ef2eec57f61f45da32b363e9b77b6cdda3de545b82ff5fce506f5970509b998b195d229625ca590e496b2679cd7fc18da61497a478226cf69b73c04be136189d
6
+ metadata.gz: dc7157372663dc871a85b36ee042e0fc12b66ad45fb322398b593086b47896167ab4cb913ab8b1f636071a9a006d2a3ab3af34b6d32e4024d7f3121dc4d9e19c
7
+ data.tar.gz: 6b0b7c59f66be811b16322574f8f0670c5802760b8cf8e690b3d4fa4107ea17dffa1e085c0c9607a72fa0a025eef0665087d5b18b0d671e43bab1cf7b5eea95f
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
@@ -0,0 +1,77 @@
1
+ #TODO: rebuild to handle event squashing on rust side
2
+
3
+ require 'ostruct'
4
+
5
+ require_relative './ffi.rb'
6
+
7
+
8
+ module Hakuban
9
+
10
+ class Event < OpenStruct; end
11
+
12
+ class ObjectDescriptorCallbackEventQueue
13
+
14
+ def initialize(pointer)
15
+ @events_pointer = ::FFI::AutoPointer.new(pointer, proc { |ptr| FFI.hakuban_object_descriptor_events_return(ptr) })
16
+ end
17
+
18
+
19
+ # WARNING: this callback may be run from a separate, non-ruby, thread
20
+ def callback_register(&callback)
21
+ ffi_callback = proc { |_userdata, ffi_descriptor, ffi_action|
22
+ action = Hakuban::action_int_to_symbol(ffi_action)
23
+ descriptor = ObjectDescriptor.from_ffi(ffi_descriptor)
24
+ callback.call(descriptor, action)
25
+ }
26
+ @callback_pointer = ::FFI::AutoPointer.new(
27
+ FFI::hakuban_object_descriptor_events_callback_register(@events_pointer, ffi_callback, ::FFI::Pointer::NULL),
28
+ proc { |ptr| FFI::hakuban_object_descriptor_events_callback_unregister(ptr) }
29
+ )
30
+ end
31
+
32
+
33
+ def callback_unregister
34
+ @callback_pointer.free
35
+ @callback_pointer = nil
36
+ end
37
+
38
+
39
+ def drop
40
+ @events_pointer.free
41
+ @events_pointer = nil
42
+ end
43
+
44
+ end
45
+
46
+
47
+ class ObjectDescriptorEventQueue
48
+
49
+ def initialize(contract)
50
+ @contract = contract
51
+ @queue = Queue.new
52
+ @ffi_callback = proc { |descriptor, action|
53
+ @queue << Hakuban::Event.new(action: action, descriptor: descriptor)
54
+ }
55
+ @ffi_events = @contract.new_callback_event_queue
56
+ @ffi_events.callback_register(&@ffi_callback)
57
+ end
58
+
59
+
60
+ #def push(event)
61
+ # @queue << event
62
+ #end
63
+
64
+
65
+ def next_event; next_change; end
66
+ def next_change
67
+ @queue.pop
68
+ end
69
+
70
+
71
+ def close
72
+ @queue.close
73
+ end
74
+
75
+ end
76
+
77
+ 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,10 +25,18 @@ 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
35
42
  attr_accessor :data_type_strings
@@ -58,7 +65,7 @@ module Hakuban::FFI
58
65
  end
59
66
 
60
67
  class FFITagObserveObjectStateBorrowResult < FFI::Struct
61
- layout :error, :uint8, :state, FFIObjectObserveState.by_value
68
+ layout :error, :uint8, :state, :pointer
62
69
  end
63
70
 
64
71
  class FFIObjectDescriptor < FFI::Struct
@@ -122,30 +129,41 @@ module Hakuban::FFI
122
129
 
123
130
  attach_function :hakuban_object_observe_new, [ :pointer, FFIObjectDescriptor.by_value ], FFIObjectObserveResult.by_value, blocking: true
124
131
  attach_function :hakuban_object_observe_drop, [ :pointer ], :void, blocking: true
125
- attach_function :hakuban_object_observe_state_borrow, [ :pointer ], FFIObjectObserveState.by_value, blocking: true
126
- attach_function :hakuban_object_observe_changes_callback_register, [ :pointer, :object_callback, :pointer ], :pointer, blocking: true
127
-
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
+
128
135
  attach_function :hakuban_object_expose_new, [ :pointer, FFIObjectDescriptor.by_value], FFIObjectExposeResult.by_value, blocking: true
129
136
  attach_function :hakuban_object_expose_drop, [ :pointer ], :void, blocking: true
130
- attach_function :hakuban_object_expose_state, [ :pointer, FFIObjectExposeState.by_value ], FFIObjectExposeStateResult.by_value, blocking: true
131
- attach_function :hakuban_object_expose_assigned, [ :pointer ], :uint8, blocking: true
132
- 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
133
141
 
134
142
  attach_function :hakuban_tag_observe_new, [ :pointer, FFITagDescriptor.by_value ], FFITagObserveResult.by_value, blocking: true
135
143
  attach_function :hakuban_tag_observe_drop, [ :pointer ], :void, blocking: true
136
144
  attach_function :hakuban_tag_observe_object_descriptors_borrow, [ :pointer ], FFIObjectDescriptors.by_value, blocking: true
137
145
  attach_function :hakuban_tag_observe_object_state_borrow, [ :pointer, FFIObjectDescriptor.by_value ], FFITagObserveObjectStateBorrowResult.by_value, blocking: true
138
- 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
139
147
 
140
148
  attach_function :hakuban_tag_expose_new, [ :pointer, FFITagDescriptor.by_value ], FFITagExposeResult.by_value, blocking: true
141
149
  attach_function :hakuban_tag_expose_drop, [ :pointer ], :void, blocking: true
142
150
  attach_function :hakuban_tag_expose_object_descriptors_borrow, [ :pointer ], FFIObjectDescriptors.by_value, blocking: true
143
- attach_function :hakuban_tag_expose_object_state, [ :pointer, FFIObjectDescriptor.by_value, FFIObjectExposeState.by_value ], FFIObjectExposeStateResult.by_value, blocking: true
144
- 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
160
+
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
145
164
 
146
- attach_function :hakuban_object_observe_state_return, [ FFIObjectObserveState.by_value ], :void
165
+ attach_function :hakuban_object_observe_state_return, [ :pointer ], :void
147
166
  attach_function :hakuban_object_descriptors_return, [ FFIObjectDescriptors.by_value ], :void
148
- attach_function :hakuban_object_callback_unregister, [ :pointer ], :void, blocking: true
149
167
 
150
168
  attach_function :hakuban_tokio_init_multi_thread, [ :size_t ], :pointer
151
169
  attach_function :hakuban_tokio_websocket_connector_new, [ :pointer, :pointer, :string ], FFITokioWebsocketConnectorNewResult.by_value