hakuban 0.5.0 → 0.5.1
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 +4 -4
- data/lib/hakuban/ffi.rb +12 -8
- data/lib/hakuban/hakuban.rb +131 -36
- data/lib/hakuban/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aca4a31cd75c69917785c7d5d3110c9db07d44c9be8394b37714fcae3019b5f6
|
4
|
+
data.tar.gz: a3c81f4d62a36fbac4bbdf6cf709909bcc132b4330e62de9b2fb39ddd4e48e72
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3a59840edfda985efda0031603f8901a24026b6edcc044f6ac61f3c04d6e8c4cae9199eb2b10b8496810b4182f85337907ee518f3d136c4a8bb829f10f66eb9d
|
7
|
+
data.tar.gz: bf7e24798ea39f0524075fcacc5a47bf8f060d72a797d2b7b92827be1b6cda252df2e8da8e64cd4c8e937b2ef08f5ae21e87ff15e3174ed9164ef2a6b64d7642
|
data/lib/hakuban/ffi.rb
CHANGED
@@ -32,6 +32,7 @@ module Hakuban::FFI
|
|
32
32
|
|
33
33
|
class FFIObjectExposeState < FFI::Struct
|
34
34
|
layout :version_length, :size_t, :version, :pointer, :data_type_length, :size_t, :data_type, :pointer, :raw_length, :size_t, :raw, :pointer
|
35
|
+
attr_accessor :data_type_strings
|
35
36
|
|
36
37
|
def self.construct(version, data_type, data)
|
37
38
|
state = FFIObjectExposeState::new
|
@@ -40,7 +41,8 @@ module Hakuban::FFI
|
|
40
41
|
state[:version].write_array_of_int64(version)
|
41
42
|
state[:data_type_length] = data_type.size
|
42
43
|
state[:data_type] = FFI::MemoryPointer.new(:pointer, data_type.size)
|
43
|
-
state
|
44
|
+
state.data_type_strings = data_type.map {|string| FFI::MemoryPointer.from_string(string)}
|
45
|
+
state[:data_type].write_array_of_pointer(state.data_type_strings)
|
44
46
|
state[:raw] = FFI::MemoryPointer.from_string(data)
|
45
47
|
state[:raw_length] = data.size
|
46
48
|
state
|
@@ -61,7 +63,8 @@ module Hakuban::FFI
|
|
61
63
|
|
62
64
|
class FFIObjectDescriptor < FFI::Struct
|
63
65
|
layout :tags_count, :size_t, :tags, :pointer, :json, :pointer
|
64
|
-
|
66
|
+
attr_accessor :tags_strings
|
67
|
+
|
65
68
|
def tags
|
66
69
|
self[:tags].read_array_of_pointer(self[:tags_count]).map { |string| JSON.parse(string.read_string()) } # does this copy the string?
|
67
70
|
end
|
@@ -71,12 +74,11 @@ module Hakuban::FFI
|
|
71
74
|
end
|
72
75
|
|
73
76
|
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
77
|
descriptor = FFIObjectDescriptor.new
|
78
78
|
descriptor[:tags_count] = tags.size
|
79
|
-
descriptor
|
79
|
+
descriptor.tags_strings = tags.map { |tag| FFI::MemoryPointer.from_string(JSON.dump(tag)) }
|
80
|
+
descriptor[:tags] = FFI::MemoryPointer.new(:pointer, descriptor.tags_strings.size)
|
81
|
+
descriptor[:tags].write_array_of_pointer(descriptor.tags_strings)
|
80
82
|
descriptor[:json] = FFI::MemoryPointer.from_string(JSON.dump(json))
|
81
83
|
descriptor
|
82
84
|
end
|
@@ -146,7 +148,9 @@ module Hakuban::FFI
|
|
146
148
|
attach_function :hakuban_object_callback_unregister, [ :pointer ], :void, blocking: true
|
147
149
|
|
148
150
|
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 :
|
151
|
+
attach_function :hakuban_tokio_websocket_connector_new, [ :pointer, :pointer, :string ], FFITokioWebsocketConnectorNewResult.by_value
|
152
|
+
attach_function :hakuban_tokio_websocket_connector_drop, [ :pointer, :pointer ], :void
|
153
|
+
|
154
|
+
attach_function :hakuban_logger_initialize, [ :string ], :uint8
|
151
155
|
|
152
156
|
end
|
data/lib/hakuban/hakuban.rb
CHANGED
@@ -4,6 +4,8 @@ require_relative './ffi.rb'
|
|
4
4
|
|
5
5
|
#TODO: explicit drops?
|
6
6
|
#TODO: privative methods
|
7
|
+
#TODO: error classes
|
8
|
+
|
7
9
|
|
8
10
|
module Hakuban
|
9
11
|
|
@@ -28,6 +30,19 @@ module Hakuban
|
|
28
30
|
end
|
29
31
|
|
30
32
|
|
33
|
+
@@logger_initialized = false
|
34
|
+
|
35
|
+
def self.logger_initialize(default_level, skip_if_already_initialized = false)
|
36
|
+
if @@logger_initialized and !skip_if_already_initialized
|
37
|
+
raise "Logger already initialized. This can't be done more than once. Make sure logger_initialize is called before any LocalNode gets constructed."
|
38
|
+
end
|
39
|
+
if not @@logger_initialized
|
40
|
+
raise "Invalid default log level string" if FFI::hakuban_logger_initialize(default_level) != 0
|
41
|
+
@@logger_initialized = true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
31
46
|
class LocalNode
|
32
47
|
|
33
48
|
#TODO: explicit drop
|
@@ -35,7 +50,8 @@ module Hakuban
|
|
35
50
|
attr_reader :local_node_pointer #todo: hide
|
36
51
|
|
37
52
|
def initialize(name=nil)
|
38
|
-
|
53
|
+
Hakuban::logger_initialize("hakuban=warn", true)
|
54
|
+
result = FFI::hakuban_local_node_new(name || File.basename(caller_locations(0..1)[1].path))
|
39
55
|
Hakuban::raise_if_error(result)
|
40
56
|
@local_node_pointer = ::FFI::AutoPointer.new(result[:local_node_pointer], FFI::method(:hakuban_local_node_drop))
|
41
57
|
end
|
@@ -111,6 +127,11 @@ module Hakuban
|
|
111
127
|
def hash
|
112
128
|
[@tags.hash, @json.hash].hash
|
113
129
|
end
|
130
|
+
|
131
|
+
def inspect
|
132
|
+
"#<ObjectDescriptor @tags={%s}, @json=%p>"%[self.tags.map(&:inspect).join(","), self.json]
|
133
|
+
end
|
134
|
+
|
114
135
|
end
|
115
136
|
|
116
137
|
|
@@ -213,12 +234,13 @@ module Hakuban
|
|
213
234
|
def drop
|
214
235
|
@object_observe_pointer.free
|
215
236
|
@object_observe_pointer = nil
|
216
|
-
@queues.values.each { |pointer| pointer.free }
|
217
237
|
@queues.clear
|
218
238
|
end
|
219
239
|
|
220
|
-
def manage(
|
221
|
-
|
240
|
+
def manage(manager=nil)
|
241
|
+
manager ||= ObjectManager.new
|
242
|
+
manager.contract = self
|
243
|
+
manager
|
222
244
|
end
|
223
245
|
|
224
246
|
end
|
@@ -264,15 +286,20 @@ module Hakuban
|
|
264
286
|
@queues.delete(queue)
|
265
287
|
end
|
266
288
|
|
289
|
+
def inspect
|
290
|
+
"#<ObjectExpose #{@descriptor}>"
|
291
|
+
end
|
292
|
+
|
267
293
|
def drop
|
268
294
|
@object_expose_pointer.free
|
269
295
|
@object_expose_pointer = nil
|
270
|
-
@queues.values.each { |pointer| pointer.free }
|
271
296
|
@queues.clear
|
272
297
|
end
|
273
298
|
|
274
|
-
def manage(
|
275
|
-
|
299
|
+
def manage(manager=nil)
|
300
|
+
manager ||= ObjectManager.new
|
301
|
+
manager.contract = self
|
302
|
+
manager
|
276
303
|
end
|
277
304
|
|
278
305
|
end
|
@@ -280,7 +307,7 @@ module Hakuban
|
|
280
307
|
|
281
308
|
class ObjectObserveState
|
282
309
|
|
283
|
-
attr_reader :data, :data_type, :data_version
|
310
|
+
attr_reader :data, :data_type, :data_version, :synchronized
|
284
311
|
|
285
312
|
def initialize(raw_state)
|
286
313
|
@raw_state = raw_state
|
@@ -302,7 +329,7 @@ module Hakuban
|
|
302
329
|
end
|
303
330
|
|
304
331
|
def inspect
|
305
|
-
"#<ObjectObserveState version
|
332
|
+
"#<ObjectObserveState @synchronized=%p @version=%p>"%[@synchronized, @data_version]
|
306
333
|
end
|
307
334
|
|
308
335
|
end
|
@@ -357,12 +384,13 @@ module Hakuban
|
|
357
384
|
def drop
|
358
385
|
@tag_observe_pointer.free
|
359
386
|
@tag_observe_pointer = nil
|
360
|
-
@queues.values.each { |pointer| pointer.free }
|
361
387
|
@queues.clear
|
362
388
|
end
|
363
389
|
|
364
|
-
def manage(
|
365
|
-
ObjectManager
|
390
|
+
def manage(manager=nil)
|
391
|
+
manager ||= ObjectManager.new
|
392
|
+
manager.contract = self
|
393
|
+
manager
|
366
394
|
end
|
367
395
|
|
368
396
|
end
|
@@ -418,12 +446,13 @@ module Hakuban
|
|
418
446
|
def drop
|
419
447
|
@tag_expose_pointer.free
|
420
448
|
@tag_expose_pointer = nil
|
421
|
-
@queues.values.each { |pointer| pointer.free }
|
422
449
|
@queues.clear
|
423
450
|
end
|
424
451
|
|
425
|
-
def manage(
|
426
|
-
ObjectManager
|
452
|
+
def manage(manager=nil)
|
453
|
+
manager ||= ObjectManager.new
|
454
|
+
manager.contract = self
|
455
|
+
manager
|
427
456
|
end
|
428
457
|
|
429
458
|
end
|
@@ -452,10 +481,10 @@ module Hakuban
|
|
452
481
|
|
453
482
|
#TODO: drop
|
454
483
|
|
455
|
-
def initialize(url)
|
456
|
-
result = FFI::hakuban_tokio_websocket_connector_new(Tokio.pointer, url)
|
484
|
+
def initialize(local_node, url)
|
485
|
+
result = FFI::hakuban_tokio_websocket_connector_new(Tokio.pointer, local_node.local_node_pointer, url)
|
457
486
|
Hakuban::raise_if_error(result)
|
458
|
-
@websocket_connector_pointer = result[:websocket_connector_pointer]
|
487
|
+
@websocket_connector_pointer = ::FFI::AutoPointer.new(result[:websocket_connector_pointer], WebsocketConnector.generate_drop)
|
459
488
|
end
|
460
489
|
|
461
490
|
def start(local_node)
|
@@ -464,38 +493,99 @@ module Hakuban
|
|
464
493
|
self
|
465
494
|
end
|
466
495
|
|
496
|
+
def self.generate_drop
|
497
|
+
proc { |pointer|
|
498
|
+
FFI::hakuban_tokio_websocket_connector_drop(Tokio.pointer, pointer)
|
499
|
+
}
|
500
|
+
end
|
501
|
+
|
467
502
|
end
|
468
503
|
|
469
504
|
|
470
505
|
# convenience utils
|
471
506
|
|
472
|
-
|
507
|
+
#TODO: replace this mess (<Hash, dynamic mixings) with some "deref"
|
508
|
+
class ObjectManager < Hash
|
509
|
+
|
510
|
+
module ObservedObjectManager
|
511
|
+
def descriptor; self.values.first.descriptor; end
|
512
|
+
def state; self.values.first.state; end
|
513
|
+
def data; self.values.first.data; end
|
514
|
+
def version; self.values.first.verison; end
|
515
|
+
def synchronized; self.values.first.synchronized; end
|
516
|
+
def construct_object(contract, descriptor); ObservedObject.new(contract, descriptor); end
|
517
|
+
end
|
518
|
+
|
519
|
+
module ExposedObjectManager
|
520
|
+
def descriptor; self.values.first.descriptor; end
|
521
|
+
def state=(params); self.values.first.state = params; end
|
522
|
+
def data=(params); self.values.first.data = params; end
|
523
|
+
def state_set(params); self.values.first.state_set(params); end
|
524
|
+
def data_set(params); self.values.first.data_set(params); end
|
525
|
+
def construct_object(contract, descriptor); ExposedObject.new(contract, descriptor); end
|
526
|
+
end
|
527
|
+
|
528
|
+
module ObservedTagManager
|
529
|
+
def construct_object(contract, descriptor); ObservedObject.new(contract, descriptor); end
|
530
|
+
end
|
531
|
+
|
532
|
+
module ExposedTagManager
|
533
|
+
def construct_object(contract, descriptor); ExposedObject.new(contract, descriptor); end
|
534
|
+
end
|
473
535
|
|
474
536
|
attr_reader :objects, :contract
|
475
537
|
|
476
|
-
def
|
538
|
+
def contract=(contract)
|
539
|
+
raise "You can't change contracts, sorry." if @contract
|
477
540
|
@contract = contract
|
478
|
-
@
|
541
|
+
case @contract.class.name
|
542
|
+
when "Hakuban::ObjectObserve" then singleton_class.include(ObservedObjectManager)
|
543
|
+
when "Hakuban::ObjectExpose" then singleton_class.include(ExposedObjectManager)
|
544
|
+
when "Hakuban::TagObserve" then singleton_class.include(ObservedTagManager)
|
545
|
+
when "Hakuban::TagExpose" then singleton_class.include(ExposedTagManager)
|
546
|
+
else raise
|
547
|
+
end
|
548
|
+
|
479
549
|
@queue = Queue.new
|
480
|
-
contract.send_events_to(@queue, :object)
|
550
|
+
@contract.send_events_to(@queue, :object)
|
551
|
+
if @contract.kind_of?(ObjectObserve) or @contract.kind_of?(ObjectExpose)
|
552
|
+
event, param, descriptor = @queue.pop
|
553
|
+
raise if event != :object or param != :insert or not descriptor
|
554
|
+
self[descriptor] = self.construct_object(@contract, descriptor)
|
555
|
+
end
|
556
|
+
|
481
557
|
@thread = Thread.new {
|
482
558
|
loop {
|
483
|
-
event = @queue.shift
|
484
|
-
case event
|
559
|
+
event,param,descriptor = @queue.shift
|
560
|
+
case [event, param]
|
485
561
|
when [:control, :quit]
|
486
562
|
break
|
487
563
|
when [:object, :insert]
|
488
|
-
|
564
|
+
self[descriptor] = construct_object(@contract, descriptor)
|
565
|
+
object_insert(self[descriptor])
|
489
566
|
when [:object, :change]
|
490
|
-
|
567
|
+
object_change(self[descriptor])
|
491
568
|
when [:object, :remove]
|
492
|
-
|
493
|
-
deleted.drop if deleted.respond_to?(:drop)
|
569
|
+
object_remove(delete(descriptor))
|
494
570
|
end
|
495
571
|
}
|
496
572
|
}
|
497
573
|
end
|
498
574
|
|
575
|
+
|
576
|
+
def object_insert(object)
|
577
|
+
# noop default
|
578
|
+
end
|
579
|
+
|
580
|
+
def object_change(object)
|
581
|
+
# noop default
|
582
|
+
end
|
583
|
+
|
584
|
+
def object_remove(object)
|
585
|
+
# noop default
|
586
|
+
end
|
587
|
+
|
588
|
+
|
499
589
|
def drop
|
500
590
|
@contract.stop_sending_objects_events_to(@queue)
|
501
591
|
@queue.push [:control, :quit]
|
@@ -509,11 +599,10 @@ module Hakuban
|
|
509
599
|
def initialize(contract, descriptor)
|
510
600
|
@contract, @descriptor = contract, descriptor
|
511
601
|
end
|
512
|
-
end
|
513
|
-
|
602
|
+
end
|
514
603
|
|
515
|
-
#TODO:
|
516
|
-
|
604
|
+
#TODO: remove the arity thing...
|
605
|
+
class ObservedObject < ManagedObject
|
517
606
|
def state
|
518
607
|
if @contract.method(:object_state).arity == 1
|
519
608
|
@contract.object_state(@descriptor)
|
@@ -530,22 +619,28 @@ module Hakuban
|
|
530
619
|
end
|
531
620
|
end
|
532
621
|
|
533
|
-
|
534
|
-
def
|
622
|
+
class ExposedObject < ManagedObject
|
623
|
+
def state_set(state)
|
535
624
|
if @contract.method(:set_object_state).arity == 4
|
536
625
|
@contract.set_object_state(@descriptor, *state)
|
537
626
|
else
|
538
627
|
@contract.set_object_state(*state)
|
539
628
|
end
|
540
629
|
end
|
541
|
-
def
|
542
|
-
|
630
|
+
def state=(state)
|
631
|
+
state_set(state)
|
632
|
+
end
|
633
|
+
def data_set(value)
|
634
|
+
timestamp = Time.new.to_f
|
543
635
|
if @contract.method(:set_object_state).arity == 4
|
544
636
|
@contract.set_object_state(@descriptor,[1, timestamp.floor, ((timestamp - timestamp.floor)*1000000000).floor, 0],[],value)
|
545
637
|
else
|
546
638
|
@contract.set_object_state([1, timestamp.floor, ((timestamp - timestamp.floor)*1000000000).floor, 0],[],value)
|
547
639
|
end
|
548
640
|
end
|
641
|
+
def data=(value)
|
642
|
+
data_set(value)
|
643
|
+
end
|
549
644
|
end
|
550
645
|
end
|
551
646
|
|
data/lib/hakuban/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hakuban
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- yunta
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-07-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|