zold 0.22.0 → 0.22.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: 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