zold 0.22.0 → 0.22.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 396a65bbca7258f8feecc54b1474e49805316f4088bbc7a9a6f1e62ff5a33ac8
4
- data.tar.gz: 5172b79f8b015f94ad90a4453e110778d7f21a75b2e6643a77e009ecb8244987
3
+ metadata.gz: d50cb5eed786603d787de81db031216d416178af36f172b539d75fcdb944546d
4
+ data.tar.gz: f7839b40f6749768636948106d61a10c0251156bcc24b7e5012d9f10964daac1
5
5
  SHA512:
6
- metadata.gz: f2dfba67609c3021e6f7504a7fbd077d45388f4aad4e0aeca8475f624ee7fa37df8d262efad99250b304d6169ed735e8de739e766869d91fa601be080744db92
7
- data.tar.gz: a27154e642518f971672bc210aeeb81c5291a307c9ecc04daf1a7e781637033fe25dd1f343994ca1a696bf2c0b43939e1210b1f4c3d6a11aee934c2b9efce2f4
6
+ metadata.gz: cb8a213e6d5f13fae1c35f051caf3a9c8ade80d6199352f9d640544802ab603a0ae6d39a3a190c548350a0078d98149e7bdc5a67c421fc7dd441b387852585bf
7
+ data.tar.gz: 274a6a6ae2f7265bc76e6480aa93e21d7631efe33c77bbacc2612d9b1b00b1fbd23ec6c429d66a68ac4faacb885387331e169a77143f364e45e47366bdcd7e3b
data/bin/zold CHANGED
@@ -34,6 +34,7 @@ require_relative '../lib/zold'
34
34
  require_relative '../lib/zold/version'
35
35
  require_relative '../lib/zold/wallet'
36
36
  require_relative '../lib/zold/dir_items'
37
+ require_relative '../lib/zold/hands'
37
38
  require_relative '../lib/zold/wallets'
38
39
  require_relative '../lib/zold/tree_wallets'
39
40
  require_relative '../lib/zold/sync_wallets'
@@ -195,6 +196,8 @@ copies = File.join(zdata, 'copies')
195
196
  log.debug("Network: #{opts['network']} (#{opts['network'] == Zold::Wallet::MAINET ? 'main' : 'test'} net)")
196
197
  log.debug("Memory footprint at start is #{Zold::Size.new(GetProcessMem.new.bytes.to_i)}")
197
198
 
199
+ Zold::Hands.start
200
+
198
201
  cmd = lambda do
199
202
  begin
200
203
  case command
@@ -281,4 +284,6 @@ else
281
284
  log.debug("Successfully finished in #{Zold::Age.new(start)}")
282
285
  end
283
286
 
287
+ Zold::Hands.stop
288
+
284
289
  abort # We need this in case some threads are still alive
@@ -34,6 +34,7 @@ require_relative '../log'
34
34
  require_relative '../http'
35
35
  require_relative '../copies'
36
36
  require_relative '../thread_pool'
37
+ require_relative '../hands'
37
38
 
38
39
  # CLEAN command.
39
40
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -53,13 +54,13 @@ module Zold
53
54
  o.banner = "Usage: zold clean [ID...] [options]
54
55
  Available options:"
55
56
  o.integer '--threads',
56
- "How many threads to use for cleaning copies (default: #{[Concurrent.processor_count / 2, 2].max})",
57
- default: [Concurrent.processor_count / 2, 2].max
57
+ 'How many threads to use for cleaning copies (default: 1)',
58
+ default: 1
58
59
  o.bool '--help', 'Print instructions'
59
60
  end
60
61
  mine = Args.new(opts, @log).take || return
61
62
  list = mine.empty? ? @wallets.all : mine.map { |i| Id.new(i) }
62
- ThreadPool.new('clean', log: @log).run(opts['threads'], list.uniq) do |id|
63
+ Hands.exec(opts['threads'], list.uniq) do |id|
63
64
  clean(Copies.new(File.join(@copies, id), log: @log), opts)
64
65
  end
65
66
  end
@@ -33,6 +33,7 @@ require 'concurrent'
33
33
  require_relative 'thread_badge'
34
34
  require_relative 'args'
35
35
  require_relative '../thread_pool'
36
+ require_relative '../hands'
36
37
  require_relative '../log'
37
38
  require_relative '../age'
38
39
  require_relative '../http'
@@ -94,7 +95,7 @@ Available options:"
94
95
  end
95
96
  mine = Args.new(opts, @log).take || return
96
97
  list = mine.empty? ? @wallets.all : mine.map { |i| Id.new(i) }
97
- ThreadPool.new('fetch', log: @log).run(opts['threads'], list.uniq) do |id|
98
+ Hands.exec(opts['threads'], list.uniq) do |id|
98
99
  fetch(id, Copies.new(File.join(@copies, id)), opts)
99
100
  end
100
101
  end
@@ -28,6 +28,7 @@ require 'concurrent'
28
28
  require_relative 'thread_badge'
29
29
  require_relative 'args'
30
30
  require_relative '../thread_pool'
31
+ require_relative '../hands'
31
32
  require_relative '../age'
32
33
  require_relative '../size'
33
34
  require_relative '../log'
@@ -85,7 +86,7 @@ Available options:"
85
86
  end
86
87
  mine = Args.new(opts, @log).take || return
87
88
  list = mine.empty? ? @wallets.all : mine.map { |i| Id.new(i) }
88
- ThreadPool.new('push', log: @log).run(opts['threads'], list.uniq) do |id|
89
+ Hands.exec(opts['threads'], list.uniq) do |id|
89
90
  push(id, opts)
90
91
  end
91
92
  end
data/lib/zold/hands.rb ADDED
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2018-2019 Zerocracy, Inc.
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'concurrent'
24
+ require_relative 'thread_pool'
25
+ require_relative 'endless'
26
+
27
+ # Multiple threads that can do something useful together.
28
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
29
+ # Copyright:: Copyright (c) 2018 Yegor Bugayenko
30
+ # License:: MIT
31
+ module Zold
32
+ # Hands
33
+ class Hands
34
+ # Pool of threads
35
+ POOL = ThreadPool.new('default')
36
+ private_constant :POOL
37
+
38
+ # Queue of jobs
39
+ QUEUE = Queue.new
40
+ private_constant :QUEUE
41
+
42
+ # Start
43
+ def self.start(max = Concurrent.processor_count * 8)
44
+ while POOL.count < max
45
+ POOL.add do
46
+ Endless.new('hands').run do
47
+ QUEUE.pop.call
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ # Stop
54
+ def self.stop
55
+ POOL.kill
56
+ end
57
+
58
+ # Run this code in many threads
59
+ def self.exec(threads, set = (0..threads - 1).to_a)
60
+ raise 'The thread pool is empty' if POOL.empty?
61
+ raise "Number of threads #{threads} has to be positive" unless threads.positive?
62
+ list = set.dup
63
+ total = [threads, set.count].min
64
+ if total == 1
65
+ list.each_with_index { |r, i| yield(r, i) }
66
+ elsif total.positive?
67
+ idx = Concurrent::AtomicFixnum.new
68
+ mutex = Mutex.new
69
+ latch = Concurrent::CountDownLatch.new(total)
70
+ errors = Set.new
71
+ total.times do |i|
72
+ QUEUE.push(
73
+ lambda do
74
+ Thread.current.name = "#{@title}-#{i}"
75
+ loop do
76
+ r = mutex.synchronize { list.pop }
77
+ break if r.nil?
78
+ yield(r, idx.increment - 1)
79
+ end
80
+ rescue StandardError => e
81
+ errors << e
82
+ raise e
83
+ ensure
84
+ latch.count_down
85
+ end
86
+ )
87
+ end
88
+ latch.wait
89
+ raise errors.to_a[0] unless errors.empty?
90
+ end
91
+ end
92
+ end
93
+ end
data/lib/zold/remotes.rb CHANGED
@@ -31,6 +31,7 @@ require 'backtrace'
31
31
  require 'zold/score'
32
32
  require_relative 'age'
33
33
  require_relative 'http'
34
+ require_relative 'hands'
34
35
  require_relative 'thread_pool'
35
36
  require_relative 'node/farm'
36
37
 
@@ -188,7 +189,7 @@ module Zold
188
189
  def iterate(log, farm: Farm::Empty.new)
189
190
  raise 'Log can\'t be nil' if log.nil?
190
191
  raise 'Farm can\'t be nil' if farm.nil?
191
- ThreadPool.new('remotes', log: log).run(Concurrent.processor_count * 4, all) do |r, idx|
192
+ Hands.exec(Concurrent.processor_count * 4, all) do |r, idx|
192
193
  Thread.current.name = "remotes-#{idx}@#{r[:host]}:#{r[:port]}"
193
194
  start = Time.now
194
195
  best = farm.best[0]
@@ -38,34 +38,6 @@ module Zold
38
38
  @start = Time.now
39
39
  end
40
40
 
41
- # Run this code in many threads
42
- def run(threads, set = (0..threads - 1).to_a)
43
- raise "Number of threads #{threads} has to be positive" unless threads.positive?
44
- list = set.dup
45
- total = [threads, set.count].min
46
- if total == 1
47
- list.each_with_index { |r, i| yield(r, i) }
48
- elsif total.positive?
49
- idx = Concurrent::AtomicFixnum.new
50
- mutex = Mutex.new
51
- latch = Concurrent::CountDownLatch.new(total)
52
- total.times do |i|
53
- add do
54
- Thread.current.name = "#{@title}-#{i}"
55
- loop do
56
- r = mutex.synchronize { list.pop }
57
- break if r.nil?
58
- yield(r, idx.increment - 1)
59
- end
60
- ensure
61
- latch.count_down
62
- end
63
- end
64
- latch.wait
65
- kill
66
- end
67
- end
68
-
69
41
  # Add a new thread
70
42
  def add
71
43
  raise 'Block must be given to start()' unless block_given?
@@ -99,9 +71,7 @@ module Zold
99
71
  #{@threads.map { |t| "#{t.name}/#{t.status}" }.join(', ')}...")
100
72
  start = Time.new
101
73
  begin
102
- @threads.each do |t|
103
- t.join(0.1)
104
- end
74
+ join(0.1)
105
75
  ensure
106
76
  @threads.each do |t|
107
77
  (t.thread_variable_get(:kids) || []).each(&:kill)
@@ -118,6 +88,11 @@ it was alive for #{Age.new(@start)}: #{@threads.map { |t| "#{t.name}/#{t.status}
118
88
  end
119
89
  end
120
90
 
91
+ # Is it empty and has no threads?
92
+ def empty?
93
+ @threads.empty?
94
+ end
95
+
121
96
  # How many threads are in there
122
97
  def count
123
98
  @threads.count
data/lib/zold/version.rb CHANGED
@@ -25,7 +25,7 @@
25
25
  # Copyright:: Copyright (c) 2018 Yegor Bugayenko
26
26
  # License:: MIT
27
27
  module Zold
28
- VERSION = '0.22.0'
28
+ VERSION = '0.22.1'
29
29
  PROTOCOL = 2
30
30
  REPO = 'zold-io/zold'
31
31
  end
data/test/test__helper.rb CHANGED
@@ -40,6 +40,9 @@ if ENV['CI'] == 'true'
40
40
  SimpleCov.formatter = SimpleCov::Formatter::Codecov
41
41
  end
42
42
 
43
+ require_relative '../lib/zold/hands'
44
+ Zold::Hands.start
45
+
43
46
  module Zold
44
47
  class Test < Minitest::Test
45
48
  include Minitest::Hooks
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2018-2019 Zerocracy, Inc.
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'minitest/autorun'
24
+ require 'concurrent'
25
+ require_relative 'test__helper'
26
+ require_relative '../lib/zold/hands'
27
+
28
+ # Hands test.
29
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
30
+ # Copyright:: Copyright (c) 2018 Yegor Bugayenko
31
+ # License:: MIT
32
+ class TestHands < Zold::Test
33
+ def test_runs_in_many_threads
34
+ idx = Concurrent::AtomicFixnum.new
35
+ threads = 50
36
+ Zold::Hands.exec(threads) do
37
+ idx.increment
38
+ end
39
+ assert_equal(threads, idx.value)
40
+ end
41
+
42
+ def test_runs_with_empty_set
43
+ Zold::Hands.exec(5, []) do
44
+ # nothing
45
+ end
46
+ end
47
+
48
+ def test_runs_with_index
49
+ idx = Concurrent::AtomicFixnum.new
50
+ indexes = Set.new
51
+ Zold::Hands.exec(10, %w[a b c]) do |_, i|
52
+ idx.increment
53
+ indexes << i
54
+ end
55
+ assert_equal(3, idx.value)
56
+ assert_equal('0 1 2', indexes.to_a.sort.join(' '))
57
+ end
58
+
59
+ def test_runs_with_exceptions
60
+ assert_raises do
61
+ Zold::Hands.exec(5) do |i|
62
+ if i == 4
63
+ sleep 0.1
64
+ raise 'intended'
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -43,43 +43,6 @@ class TestThreadPool < Zold::Test
43
43
  assert_equal(threads, idx.value)
44
44
  end
45
45
 
46
- def test_runs_in_many_threads
47
- idx = Concurrent::AtomicFixnum.new
48
- threads = 50
49
- Zold::ThreadPool.new('test', log: test_log).run(threads) do
50
- idx.increment
51
- end
52
- assert_equal(threads, idx.value)
53
- end
54
-
55
- def test_runs_with_empty_set
56
- Zold::ThreadPool.new('test', log: test_log).run(5, []) do
57
- # nothing
58
- end
59
- end
60
-
61
- def test_runs_with_index
62
- idx = Concurrent::AtomicFixnum.new
63
- indexes = Set.new
64
- Zold::ThreadPool.new('test', log: test_log).run(10, %w[a b c]) do |_, i|
65
- idx.increment
66
- indexes << i
67
- end
68
- assert_equal(3, idx.value)
69
- assert_equal('0 1 2', indexes.to_a.sort.join(' '))
70
- end
71
-
72
- def test_runs_with_exceptions
73
- assert_raises do
74
- Zold::ThreadPool.new('test', log: test_log).run(5) do |i|
75
- if i == 4
76
- sleep 0.1
77
- raise 'intended'
78
- end
79
- end
80
- end
81
- end
82
-
83
46
  def test_adds_and_stops
84
47
  pool = Zold::ThreadPool.new('test', log: test_log)
85
48
  pool.add do
data/test/test_wallet.rb CHANGED
@@ -29,6 +29,7 @@ require_relative '../lib/zold/age'
29
29
  require_relative '../lib/zold/id'
30
30
  require_relative '../lib/zold/wallet'
31
31
  require_relative '../lib/zold/txn'
32
+ require_relative '../lib/zold/thread_pool'
32
33
  require_relative '../lib/zold/amount'
33
34
  require_relative '../lib/zold/commands/pay'
34
35
 
@@ -296,16 +297,17 @@ class TestWallet < Zold::Test
296
297
  end
297
298
 
298
299
  def test_collects_memory_garbage
299
- # skip
300
+ skip
300
301
  require 'get_process_mem'
301
302
  start = GetProcessMem.new.bytes.to_i
302
-
303
- 40.times do |i|
304
- wallet = Zold::Wallet.new('fixtures/448b451bc62e8e16.z')
305
- GC.start
306
- wallet.id
307
- wallet.txns.count
308
- test_log.debug("Memory: #{GetProcessMem.new.bytes.to_i}") if (i % 5).zero?
303
+ Zold::Hands.exec(20) do
304
+ 40.times do |i|
305
+ wallet = Zold::Wallet.new('fixtures/448b451bc62e8e16.z')
306
+ GC.start
307
+ wallet.id
308
+ wallet.txns.count
309
+ test_log.debug("Memory: #{GetProcessMem.new.bytes.to_i}") if (i % 5).zero?
310
+ end
309
311
  end
310
312
  GC.stress = true
311
313
  diff = GetProcessMem.new.bytes.to_i - start
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zold
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.22.0
4
+ version: 0.22.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-16 00:00:00.000000000 Z
11
+ date: 2019-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backtrace
@@ -627,6 +627,7 @@ files:
627
627
  - lib/zold/dir_items.rb
628
628
  - lib/zold/endless.rb
629
629
  - lib/zold/gem.rb
630
+ - lib/zold/hands.rb
630
631
  - lib/zold/head.rb
631
632
  - lib/zold/hexnum.rb
632
633
  - lib/zold/http.rb
@@ -709,6 +710,7 @@ files:
709
710
  - test/test_copies.rb
710
711
  - test/test_dir_items.rb
711
712
  - test/test_gem.rb
713
+ - test/test_hands.rb
712
714
  - test/test_hexnum.rb
713
715
  - test/test_http.rb
714
716
  - test/test_hungry_wallets.rb
@@ -744,7 +746,7 @@ licenses:
744
746
  - MIT
745
747
  metadata: {}
746
748
  post_install_message: |-
747
- Thanks for installing Zold 0.22.0!
749
+ Thanks for installing Zold 0.22.1!
748
750
  Study our White Paper: https://papers.zold.io/wp.pdf
749
751
  Read our blog posts: https://blog.zold.io
750
752
  Try ZLD online wallet at: https://wts.zold.io
@@ -817,6 +819,7 @@ test_files:
817
819
  - test/test_copies.rb
818
820
  - test/test_dir_items.rb
819
821
  - test/test_gem.rb
822
+ - test/test_hands.rb
820
823
  - test/test_hexnum.rb
821
824
  - test/test_http.rb
822
825
  - test/test_hungry_wallets.rb