hakuban 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 79db90522bce42223139845bf81169a9e75a2997a90e71952b0b00d852272ff6
4
- data.tar.gz: 35d50834b1a5a2626e9e3ad62c063b04acfc86569f887e57afe2578125d994cc
3
+ metadata.gz: aca4a31cd75c69917785c7d5d3110c9db07d44c9be8394b37714fcae3019b5f6
4
+ data.tar.gz: a3c81f4d62a36fbac4bbdf6cf709909bcc132b4330e62de9b2fb39ddd4e48e72
5
5
  SHA512:
6
- metadata.gz: 5d74f9761c28495c9d6caed241fb907147aff987d8c9d5526ded5d15f6e43ac781354baae9894fc74684ecad374646d8fde4cf90b26550a2e954f6bbf95f5ecb
7
- data.tar.gz: 2c48edc2b71800bf19e3a1f267de234493e1e54aa6ae6fb4042ba1fc79f22a35aa28015e2d0b37f6ddb5c491817cf6698330b609dba96077e6d26ddcd441cb28
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[:data_type].write_array_of_pointer(data_type.map {|string| FFI::MemoryPointer.from_string(string)})
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[:tags] = tags_strings_array
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 :hakuban_tokio_websocket_connector_start, [ :pointer, :pointer, :pointer ], :void
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
@@ -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
- result = FFI::hakuban_local_node_new(name || "local")
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(object_class, *object_constructor_params)
221
- object_class::new(self, @descriptor, *object_constructor_params)
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(object_class, *object_constructor_params)
275
- object_class::new(self, @descriptor, *object_constructor_params)
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=#{@data_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(object_class, *object_constructor_params)
365
- ObjectManager::new(self, object_class, *object_constructor_params)
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(object_class, *object_constructor_params)
426
- ObjectManager::new(self, object_class, *object_constructor_params)
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
- class ObjectManager
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 initialize(contract, object_class, *object_constructor_params)
538
+ def contract=(contract)
539
+ raise "You can't change contracts, sorry." if @contract
477
540
  @contract = contract
478
- @objects = {}
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[0..1]
559
+ event,param,descriptor = @queue.shift
560
+ case [event, param]
485
561
  when [:control, :quit]
486
562
  break
487
563
  when [:object, :insert]
488
- @objects[event[2]] = object_class.new(@contract, event[2], *object_constructor_params)
564
+ self[descriptor] = construct_object(@contract, descriptor)
565
+ object_insert(self[descriptor])
489
566
  when [:object, :change]
490
- @objects[event[2]].change if @objects[event[2]].respond_to?(:change)
567
+ object_change(self[descriptor])
491
568
  when [:object, :remove]
492
- raise if not deleted = @objects.delete(event[2])
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: fix the arity thing...
516
- module ObservedObject
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
- module ExposedObject
534
- def state=(state)
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 data=(value)
542
- timestamp = Time.new.to_f.floor
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
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hakuban
4
- VERSION = "0.5.0"
4
+ VERSION = "0.5.1"
5
5
  end
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.0
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-06-13 00:00:00.000000000 Z
11
+ date: 2021-07-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec