zold 0.16.12 → 0.16.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/zold/age.rb +1 -0
- data/lib/zold/commands/clean.rb +1 -1
- data/lib/zold/commands/fetch.rb +2 -2
- data/lib/zold/commands/list.rb +1 -1
- data/lib/zold/commands/merge.rb +1 -1
- data/lib/zold/commands/node.rb +2 -2
- data/lib/zold/commands/pay.rb +1 -1
- data/lib/zold/commands/push.rb +2 -2
- data/lib/zold/commands/taxes.rb +1 -1
- data/lib/zold/endless.rb +54 -0
- data/lib/zold/node/async_entrance.rb +34 -63
- data/lib/zold/node/entrance.rb +2 -1
- data/lib/zold/node/farm.rb +28 -36
- data/lib/zold/node/farmers.rb +2 -1
- data/lib/zold/node/front.rb +1 -1
- data/lib/zold/node/nodup_entrance.rb +4 -6
- data/lib/zold/node/safe_entrance.rb +2 -1
- data/lib/zold/node/spread_entrance.rb +13 -15
- data/lib/zold/node/sync_entrance.rb +1 -0
- data/lib/zold/version.rb +1 -1
- data/lib/zold/wallet.rb +1 -1
- data/test/node/test_async_entrance.rb +2 -2
- data/test/node/test_farm.rb +22 -0
- data/test/test_dir_items.rb +2 -1
- data/test/test_wallet.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec1ca28cf2d44bd430e43965a3a2ebdae2c10c149ed70e2edc38fb43295feb93
|
4
|
+
data.tar.gz: ef06fa34ba837fb99be1a935c907cbf1ad5a0a732f733b80e7e710c5d9b9f852
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a6b6aade154501ffab625707cbafcce32790b9c878a7d889a844277c7b8bc291922b8c39924d7772fd10572e5f9a1354ad65bf7cd15ee5c75b384a07f52f2dfc
|
7
|
+
data.tar.gz: c927263e4882236b28f58a7b49971b6194c0e852d57b836b0438ff22a3fcac541caea38d815d78b5aa54c5a07021fab8e4b83d5416fc4c946d6efce68d9c4f75
|
data/lib/zold/age.rb
CHANGED
data/lib/zold/commands/clean.rb
CHANGED
@@ -68,7 +68,7 @@ Available options:"
|
|
68
68
|
in #{Age.new(start, limit: 0.01)}, #{cps.all.count} left:\n" +
|
69
69
|
cps.all.map do |c|
|
70
70
|
wallet = Wallet.new(c[:path])
|
71
|
-
" #{c[:name]}: #{c[:score]} #{wallet.
|
71
|
+
" #{c[:name]}: #{c[:score]} #{wallet.mnemo} \
|
72
72
|
#{Size.new(File.size(c[:path]))}/#{Age.new(File.mtime(c[:path]))}"
|
73
73
|
end.join("\n")
|
74
74
|
)
|
data/lib/zold/commands/fetch.rb
CHANGED
@@ -93,7 +93,7 @@ Available options:"
|
|
93
93
|
@log.debug("#{cps.all.count} local copies:")
|
94
94
|
cps.all.each do |c|
|
95
95
|
wallet = Wallet.new(c[:path])
|
96
|
-
@log.debug(" #{c[:name]}: #{c[:score]} #{wallet.
|
96
|
+
@log.debug(" #{c[:name]}: #{c[:score]} #{wallet.mnemo} \
|
97
97
|
#{Size.new(File.size(c[:path]))}/#{Age.new(File.mtime(c[:path]))}")
|
98
98
|
end
|
99
99
|
end
|
@@ -128,7 +128,7 @@ Available options:"
|
|
128
128
|
raise "The balance of #{id} is #{wallet.balance} and it's not a root wallet"
|
129
129
|
end
|
130
130
|
copy = cps.add(IO.read(f), score.host, score.port, score.value)
|
131
|
-
@log.info("#{r} returned #{Size.new(body.length)} #{wallet.
|
131
|
+
@log.info("#{r} returned #{Size.new(body.length)} #{wallet.mnemo} \
|
132
132
|
#{digest(json)}/#{Age.new(json['mtime'])}/#{json['copies']}c \
|
133
133
|
as copy #{copy} of #{id} in #{Age.new(start, limit: 4)}: #{Rainbow(score.value).green} (#{json['version']})")
|
134
134
|
end
|
data/lib/zold/commands/list.rb
CHANGED
@@ -38,7 +38,7 @@ module Zold
|
|
38
38
|
def run(_ = [])
|
39
39
|
@wallets.all.each do |id|
|
40
40
|
@wallets.find(id) do |wallet|
|
41
|
-
msg = "#{id}: #{wallet.
|
41
|
+
msg = "#{id}: #{wallet.mnemo}"
|
42
42
|
msg += " (net:#{wallet.network})" if wallet.network != Wallet::MAIN_NETWORK
|
43
43
|
@log.info(msg)
|
44
44
|
end
|
data/lib/zold/commands/merge.rb
CHANGED
@@ -88,7 +88,7 @@ Available options:"
|
|
88
88
|
wallet.flush
|
89
89
|
if modified
|
90
90
|
@log.info("#{cps.count} copies with the total score of #{score} successfully merged \
|
91
|
-
into #{wallet.
|
91
|
+
into #{wallet.mnemo} in #{Age.new(start, limit: 0.1 + cps.count * 0.01)}")
|
92
92
|
else
|
93
93
|
@log.info("Nothing changed in #{wallet.id} after merge of #{cps.count} copies")
|
94
94
|
end
|
data/lib/zold/commands/node.rb
CHANGED
@@ -79,8 +79,8 @@ module Zold
|
|
79
79
|
"The strength of the score (default: #{Score::STRENGTH})",
|
80
80
|
default: Score::STRENGTH
|
81
81
|
o.integer '--threads',
|
82
|
-
"How many threads to use for scores finding (default: #{[Concurrent.processor_count,
|
83
|
-
default: [Concurrent.processor_count,
|
82
|
+
"How many threads to use for scores finding (default: #{[Concurrent.processor_count / 2, 2].max})",
|
83
|
+
default: [Concurrent.processor_count / 2, 2].max
|
84
84
|
o.bool '--dump-errors',
|
85
85
|
'Make HTTP front-end errors visible in the log (false by default)',
|
86
86
|
default: false
|
data/lib/zold/commands/pay.rb
CHANGED
@@ -115,7 +115,7 @@ Available options:"
|
|
115
115
|
@log.debug("Don't forget to do 'zold push #{from}'")
|
116
116
|
@log.info(txn.id)
|
117
117
|
tax = Tax.new(from)
|
118
|
-
@log.info("The tax debt of #{from.
|
118
|
+
@log.info("The tax debt of #{from.mnemo} is #{tax.debt} \
|
119
119
|
(#{tax.in_debt? ? 'too high' : 'still acceptable'})")
|
120
120
|
txn
|
121
121
|
end
|
data/lib/zold/commands/push.rb
CHANGED
@@ -95,7 +95,7 @@ total score for #{id} is #{total}")
|
|
95
95
|
response = r.http(uri).put(content)
|
96
96
|
@wallets.find(id) do |wallet|
|
97
97
|
if response.code == '304'
|
98
|
-
@log.info("#{r}: same version of #{wallet.
|
98
|
+
@log.info("#{r}: same version of #{wallet.mnemo} there, in #{Age.new(start, limit: 0.5)}")
|
99
99
|
return 0
|
100
100
|
end
|
101
101
|
r.assert_code(200, response)
|
@@ -104,7 +104,7 @@ total score for #{id} is #{total}")
|
|
104
104
|
r.assert_valid_score(score)
|
105
105
|
r.assert_score_ownership(score)
|
106
106
|
r.assert_score_strength(score) unless opts['ignore-score-weakness']
|
107
|
-
@log.info("#{r} accepted #{wallet.
|
107
|
+
@log.info("#{r} accepted #{wallet.mnemo} in #{Age.new(start, limit: 4)}: \
|
108
108
|
#{Rainbow(score.value).green} (#{json['version']})")
|
109
109
|
score.value
|
110
110
|
end
|
data/lib/zold/commands/taxes.rb
CHANGED
@@ -115,7 +115,7 @@ Available options:"
|
|
115
115
|
raise 'The wallet is absent' unless wallet.exists?
|
116
116
|
tax = Tax.new(wallet)
|
117
117
|
debt = total = tax.debt
|
118
|
-
@log.info("The current debt of #{wallet.
|
118
|
+
@log.info("The current debt of #{wallet.mnemo} is #{debt} (#{debt.to_i} zents), \
|
119
119
|
the balance is #{wallet.balance}: #{tax.to_text}")
|
120
120
|
unless tax.in_debt?
|
121
121
|
@log.debug("No need to pay taxes yet, while the debt is less than #{Tax::TRIAL} (#{Tax::TRIAL.to_i} zents)")
|
data/lib/zold/endless.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2018 Yegor Bugayenko
|
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_relative 'log'
|
24
|
+
require_relative 'verbose_thread'
|
25
|
+
require_relative 'age'
|
26
|
+
|
27
|
+
# Endless loop.
|
28
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
29
|
+
# Copyright:: Copyright (c) 2018 Yegor Bugayenko
|
30
|
+
# License:: MIT
|
31
|
+
module Zold
|
32
|
+
# Endless loop
|
33
|
+
class Endless
|
34
|
+
def initialize(title, log: Log::Quiet.new)
|
35
|
+
@title = title
|
36
|
+
@log = log
|
37
|
+
end
|
38
|
+
|
39
|
+
def run
|
40
|
+
start = Time.now
|
41
|
+
Thread.current.name = @title
|
42
|
+
Thread.current.abort_on_exception = true
|
43
|
+
begin
|
44
|
+
loop do
|
45
|
+
VerboseThread.new(@log).run(true) do
|
46
|
+
yield
|
47
|
+
end
|
48
|
+
end
|
49
|
+
ensure
|
50
|
+
@log.debug("Endless loop \"#{@title}\" quit in #{Age.new(start)}")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -22,11 +22,11 @@
|
|
22
22
|
|
23
23
|
require 'concurrent'
|
24
24
|
require 'futex'
|
25
|
-
|
25
|
+
require 'securerandom'
|
26
26
|
require_relative '../age'
|
27
27
|
require_relative '../size'
|
28
28
|
require_relative '../id'
|
29
|
-
require_relative '../
|
29
|
+
require_relative '../endless'
|
30
30
|
require_relative '../dir_items'
|
31
31
|
|
32
32
|
# The async entrance of the web front.
|
@@ -36,79 +36,54 @@ require_relative '../dir_items'
|
|
36
36
|
module Zold
|
37
37
|
# The entrance
|
38
38
|
class AsyncEntrance
|
39
|
-
|
40
|
-
THREADS = [Concurrent.processor_count, 4].max
|
41
|
-
|
42
|
-
# Queue length
|
43
|
-
MAX_QUEUE = Concurrent.processor_count * 64
|
44
|
-
|
45
|
-
def initialize(entrance, dir, log: Log::Quiet.new)
|
39
|
+
def initialize(entrance, dir, log: Log::Quiet.new, threads: [Concurrent.processor_count, 4].max)
|
46
40
|
@entrance = entrance
|
47
41
|
@dir = dir
|
48
42
|
@log = log
|
43
|
+
@total = threads
|
49
44
|
@mutex = Mutex.new
|
50
45
|
end
|
51
46
|
|
52
47
|
def to_json
|
53
|
-
|
54
|
-
|
55
|
-
'
|
56
|
-
|
57
|
-
'pool.running': @pool.running?
|
58
|
-
}
|
59
|
-
json['queue_age'] = opts.empty? ? 0 : Time.now - File.mtime(File.join(@dir, opts[0]))
|
60
|
-
@entrance.to_json.merge(json)
|
48
|
+
@entrance.to_json.merge(
|
49
|
+
'queue': queue.count,
|
50
|
+
'threads': @threads.count
|
51
|
+
)
|
61
52
|
end
|
62
53
|
|
63
54
|
def start
|
55
|
+
raise 'Block must be given to start()' unless block_given?
|
64
56
|
@entrance.start do
|
65
57
|
FileUtils.mkdir_p(@dir)
|
66
|
-
@
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
AsyncEntrance::THREADS.times do |t|
|
72
|
-
@pool.post do
|
73
|
-
Thread.current.name = "async-e##{t}"
|
74
|
-
loop do
|
75
|
-
VerboseThread.new(@log).run(true) { take }
|
76
|
-
break if @pool.shuttingdown?
|
77
|
-
sleep(1 + Random.rand(100) / 100)
|
58
|
+
@threads = (0..@total - 1).map do |i|
|
59
|
+
Thread.start do
|
60
|
+
Endless.new("async-e##{i}", log: @log).run do
|
61
|
+
take
|
62
|
+
sleep(1)
|
78
63
|
end
|
79
64
|
end
|
80
65
|
end
|
81
66
|
begin
|
82
67
|
yield(self)
|
83
|
-
cycle = 0
|
84
|
-
until queue.empty?
|
85
|
-
@log.info("Stopping async entrance, #{queue.count} still in the queue (cycle=#{cycle})...")
|
86
|
-
cycle += 1
|
87
|
-
raise "Can't wait for async entrance to stop for so long" if cycle > 10
|
88
|
-
sleep 1
|
89
|
-
end
|
90
68
|
ensure
|
91
|
-
@
|
92
|
-
@pool.shutdown
|
93
|
-
if @pool.wait_for_termination(10)
|
94
|
-
@log.info("Async entrance terminated peacefully with #{queue.count} wallets left in the queue")
|
95
|
-
else
|
96
|
-
@pool.kill
|
97
|
-
@log.info("Async entrance was killed, #{queue.count} wallets left in the queue")
|
98
|
-
end
|
69
|
+
@threads.each(&:kill)
|
99
70
|
end
|
100
71
|
end
|
101
72
|
end
|
102
73
|
|
103
74
|
# Always returns an array with a single ID of the pushed wallet
|
104
75
|
def push(id, body)
|
105
|
-
raise "Queue is too long (#{queue.count} wallets), try again later" if queue.count >
|
76
|
+
raise "Queue is too long (#{queue.count} wallets), try again later" if queue.count > 256
|
106
77
|
start = Time.now
|
107
|
-
|
108
|
-
|
78
|
+
loop do
|
79
|
+
uuid = SecureRandom.uuid
|
80
|
+
file = File.join(@dir, "#{id}-#{uuid}")
|
81
|
+
next if File.exist?(file)
|
82
|
+
IO.write(file, body)
|
83
|
+
@log.debug("Added #{id}/#{Size.new(body.length)} to the queue at pos.#{queue.count} \
|
84
|
+
in #{Age.new(start, limit: 0.05)}: #{uuid}")
|
85
|
+
break
|
109
86
|
end
|
110
|
-
@log.debug("Added #{id}/#{Size.new(body.length)} to the queue at pos.#{queue.count} \
|
111
|
-
in #{Age.new(start, limit: 0.05)}")
|
112
87
|
[id]
|
113
88
|
end
|
114
89
|
|
@@ -116,27 +91,23 @@ in #{Age.new(start, limit: 0.05)}")
|
|
116
91
|
|
117
92
|
def take
|
118
93
|
start = Time.now
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
94
|
+
id, body = @mutex.synchronize do
|
95
|
+
opts = queue
|
96
|
+
return if opts.empty?
|
97
|
+
file = File.join(@dir, opts[0])
|
98
|
+
id = opts[0].split('-')[0]
|
99
|
+
Thread.current.thread_variable_set(:wallet, id)
|
100
|
+
body = IO.read(file)
|
101
|
+
FileUtils.rm_f(file)
|
102
|
+
[id, body]
|
127
103
|
end
|
128
|
-
return if body.empty?
|
129
104
|
@entrance.push(Id.new(id), body)
|
130
105
|
@log.debug("Pushed #{id}/#{Size.new(body.length)} to #{@entrance.class.name} \
|
131
106
|
in #{Age.new(start, limit: 0.1)} (#{queue.count} still in the queue)")
|
132
107
|
end
|
133
108
|
|
134
109
|
def queue
|
135
|
-
DirItems.new(@dir).fetch.select { |f| f =~ /^[0-9a-f]{16}
|
136
|
-
end
|
137
|
-
|
138
|
-
def file(id)
|
139
|
-
File.join(@dir, id.to_s)
|
110
|
+
DirItems.new(@dir).fetch.select { |f| f =~ /^[0-9a-f]{16}-/ }
|
140
111
|
end
|
141
112
|
end
|
142
113
|
end
|
data/lib/zold/node/entrance.rb
CHANGED
@@ -51,6 +51,7 @@ module Zold
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def start
|
54
|
+
raise 'Block must be given to start()' unless block_given?
|
54
55
|
yield(self)
|
55
56
|
end
|
56
57
|
|
@@ -91,7 +92,7 @@ module Zold
|
|
91
92
|
@history.shift if @history.length >= 16
|
92
93
|
@speed.shift if @speed.length >= 64
|
93
94
|
@wallets.find(id) do |wallet|
|
94
|
-
@history << "#{id}/#{sec}/#{modified.count}/#{wallet.
|
95
|
+
@history << "#{id}/#{sec}/#{modified.count}/#{wallet.mnemo}"
|
95
96
|
end
|
96
97
|
@speed << sec
|
97
98
|
end
|
data/lib/zold/node/farm.rb
CHANGED
@@ -24,11 +24,12 @@ require 'time'
|
|
24
24
|
require 'open3'
|
25
25
|
require 'backtrace'
|
26
26
|
require 'futex'
|
27
|
+
require 'concurrent'
|
27
28
|
require 'json'
|
28
29
|
require 'zold/score'
|
29
30
|
require_relative '../log'
|
30
31
|
require_relative '../age'
|
31
|
-
require_relative '../
|
32
|
+
require_relative '../endless'
|
32
33
|
require_relative 'farmers'
|
33
34
|
|
34
35
|
# The farm of scores.
|
@@ -96,7 +97,6 @@ module Zold
|
|
96
97
|
threads: @threads.map do |t|
|
97
98
|
"#{t.name}/#{t.status}/#{t.alive? ? 'alive' : 'dead'}"
|
98
99
|
end.join(', '),
|
99
|
-
cleanup: @cleanup.status,
|
100
100
|
pipeline: @pipeline.size,
|
101
101
|
best: best.map(&:to_mnemo).join(', ')
|
102
102
|
}
|
@@ -112,41 +112,36 @@ module Zold
|
|
112
112
|
#
|
113
113
|
# The farm will stop all its threads and close all resources safely
|
114
114
|
# right after the block provided exists.
|
115
|
-
def start(host, port, strength:
|
115
|
+
def start(host, port, strength: Score::STRENGTH, threads: Concurrent.processor_count)
|
116
116
|
raise 'Block is required for the farm to start' unless block_given?
|
117
117
|
@log.info('Zero-threads farm won\'t score anything!') if threads.zero?
|
118
118
|
if best.empty?
|
119
|
-
@log.info("No scores found in cache at #{@cache}")
|
119
|
+
@log.info("No scores found in the cache at #{@cache}")
|
120
120
|
else
|
121
121
|
@log.info("#{best.size} scores pre-loaded from #{@cache}, the best is: #{best[0]}")
|
122
122
|
end
|
123
|
-
cleanup(host, port, strength, threads)
|
124
123
|
@threads = (1..threads).map do |t|
|
124
|
+
Thread.current.thread_variable_set(:tid, t.to_s)
|
125
125
|
Thread.new do
|
126
|
-
|
127
|
-
|
128
|
-
loop do
|
129
|
-
VerboseThread.new(@log).run do
|
130
|
-
cycle(host, port, strength, threads)
|
131
|
-
end
|
126
|
+
Endless.new("f#{t}", log: @log).run do
|
127
|
+
cycle(host, port, strength, threads)
|
132
128
|
end
|
133
129
|
end
|
134
130
|
end
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
end
|
131
|
+
ready = false
|
132
|
+
@threads << Thread.new do
|
133
|
+
Endless.new('cleanup', log: @log).run do
|
134
|
+
cleanup(host, port, strength, threads)
|
135
|
+
ready = true
|
136
|
+
sleep(1)
|
142
137
|
end
|
143
138
|
end
|
144
|
-
@log.info("Farm started with #{@threads.count} threads
|
145
|
-
|
139
|
+
@log.info("Farm started with #{@threads.count} threads (one for cleanup) \
|
140
|
+
at #{host}:#{port}, strength is #{strength}")
|
141
|
+
loop { break if ready }
|
146
142
|
begin
|
147
143
|
yield(self)
|
148
144
|
ensure
|
149
|
-
@cleanup.kill
|
150
145
|
@threads.each(&:kill)
|
151
146
|
@log.info("Farm stopped (threads=#{threads}, strength=#{strength})")
|
152
147
|
end
|
@@ -172,7 +167,7 @@ module Zold
|
|
172
167
|
begin
|
173
168
|
s << @pipeline.pop(true)
|
174
169
|
rescue ThreadError => _
|
175
|
-
sleep
|
170
|
+
sleep(0.25)
|
176
171
|
end
|
177
172
|
s.compact!
|
178
173
|
break unless s.empty?
|
@@ -193,7 +188,7 @@ module Zold
|
|
193
188
|
def save(threads, list = [])
|
194
189
|
scores = load + list
|
195
190
|
period = @lifetime / [threads, 1].max
|
196
|
-
Futex.new(@cache
|
191
|
+
Futex.new(@cache).open do |f|
|
197
192
|
IO.write(
|
198
193
|
f,
|
199
194
|
scores.select(&:valid?)
|
@@ -210,19 +205,16 @@ module Zold
|
|
210
205
|
end
|
211
206
|
|
212
207
|
def load
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
else
|
224
|
-
[]
|
225
|
-
end
|
208
|
+
return [] unless File.exist?(@cache)
|
209
|
+
Futex.new(@cache).open do |f|
|
210
|
+
IO.read(f).split(/\n/).map do |t|
|
211
|
+
begin
|
212
|
+
Score.parse(t)
|
213
|
+
rescue StandardError => e
|
214
|
+
@log.error(Backtrace.new(e).to_s)
|
215
|
+
nil
|
216
|
+
end
|
217
|
+
end.compact
|
226
218
|
end
|
227
219
|
end
|
228
220
|
end
|
data/lib/zold/node/farmers.rb
CHANGED
@@ -55,6 +55,7 @@ module Zold
|
|
55
55
|
'ruby',
|
56
56
|
Shellwords.escape(bin),
|
57
57
|
'--skip-upgrades',
|
58
|
+
"--info-tid=#{Thread.current.thread_variable_get(:tid)}",
|
58
59
|
"--info-thread=#{Shellwords.escape(Thread.current.name)}",
|
59
60
|
"--info-start=#{Time.now.utc.iso8601}",
|
60
61
|
'--low-priority',
|
@@ -84,7 +85,7 @@ for #{score.value}/#{score.strength} at #{score.host}:#{score.port}")
|
|
84
85
|
raise "Failed to calculate the score (##{thr.value}): #{buffer}" unless thr.value.to_i.zero?
|
85
86
|
break
|
86
87
|
end
|
87
|
-
sleep
|
88
|
+
sleep(10)
|
88
89
|
Thread.current.thread_variable_set(:buffer, buffer.length.to_s)
|
89
90
|
end
|
90
91
|
after = Score.parse(buffer.strip)
|
data/lib/zold/node/front.rb
CHANGED
@@ -334,7 +334,7 @@ in #{Age.new(@start, limit: 1)}")
|
|
334
334
|
"\n\n" +
|
335
335
|
copies.all.map do |c|
|
336
336
|
w = Wallet.new(c[:path])
|
337
|
-
"#{c[:name]}: #{c[:score]} #{w.
|
337
|
+
"#{c[:name]}: #{c[:score]} #{w.mnemo} \
|
338
338
|
#{Size.new(File.size(c[:path]))}/#{Age.new(File.mtime(c[:path]))}"
|
339
339
|
end.join("\n")
|
340
340
|
end
|
@@ -42,6 +42,7 @@ module Zold
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def start
|
45
|
+
raise 'Block must be given to start()' unless block_given?
|
45
46
|
@entrance.start { yield(self) }
|
46
47
|
end
|
47
48
|
|
@@ -63,14 +64,11 @@ module Zold
|
|
63
64
|
w.exists? ? IO.read(w.path).to_s : ''
|
64
65
|
end
|
65
66
|
if before == after
|
66
|
-
@log.info(
|
67
|
-
"Duplicate of #{Size.new(after.length)} #{wallet.memo} ignored"
|
68
|
-
)
|
67
|
+
@log.info("Duplicate of #{Size.new(after.length)} #{wallet.mnemo} ignored")
|
69
68
|
return []
|
70
69
|
end
|
71
|
-
@log.info(
|
72
|
-
|
73
|
-
)
|
70
|
+
@log.info("New content for #{wallet.mnemo} arrived, \
|
71
|
+
#{Size.new(before.length)} before and #{Size.new(after.length)} after")
|
74
72
|
@entrance.push(id, body)
|
75
73
|
end
|
76
74
|
end
|
@@ -46,6 +46,7 @@ module Zold
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def start
|
49
|
+
raise 'Block must be given to start()' unless block_given?
|
49
50
|
@entrance.start { yield(self) }
|
50
51
|
end
|
51
52
|
|
@@ -75,7 +76,7 @@ module Zold
|
|
75
76
|
Emission.new(wallet).check
|
76
77
|
tax = Tax.new(wallet)
|
77
78
|
if tax.in_debt?
|
78
|
-
raise "Taxes are not paid, can't accept the wallet #{wallet.
|
79
|
+
raise "Taxes are not paid, can't accept the wallet #{wallet.mnemo}; the debt is #{tax.debt} \
|
79
80
|
(#{tax.debt.to_i} zents); formula ingredients are #{tax.to_text}"
|
80
81
|
end
|
81
82
|
@entrance.push(id, body)
|
@@ -26,6 +26,7 @@ require_relative 'emission'
|
|
26
26
|
require_relative '../log'
|
27
27
|
require_relative '../remotes'
|
28
28
|
require_relative '../copies'
|
29
|
+
require_relative '../endless'
|
29
30
|
require_relative '../tax'
|
30
31
|
require_relative '../commands/merge'
|
31
32
|
require_relative '../commands/fetch'
|
@@ -57,26 +58,23 @@ module Zold
|
|
57
58
|
end
|
58
59
|
|
59
60
|
def start
|
61
|
+
raise 'Block must be given to start()' unless block_given?
|
60
62
|
@entrance.start do
|
61
63
|
@seen = Set.new
|
62
64
|
@modified = Queue.new
|
63
65
|
@push = Thread.start do
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
['push', "--ignore-node=#{@address}", id.to_s] +
|
75
|
-
(@ignore_score_weakeness ? ['--ignore-score-weakness'] : [])
|
76
|
-
)
|
77
|
-
end
|
78
|
-
@mutex.synchronize { @seen.delete(id) }
|
66
|
+
Endless.new('push', log: @log).run do
|
67
|
+
id = @modified.pop
|
68
|
+
if @remotes.all.empty?
|
69
|
+
@log.info("There are no remotes, won\'t spread #{id}")
|
70
|
+
else
|
71
|
+
Thread.current.thread_variable_set(:wallet, id.to_s)
|
72
|
+
Push.new(wallets: @wallets, remotes: @remotes, log: @log).run(
|
73
|
+
['push', "--ignore-node=#{@address}", id.to_s] +
|
74
|
+
(@ignore_score_weakeness ? ['--ignore-score-weakness'] : [])
|
75
|
+
)
|
79
76
|
end
|
77
|
+
@mutex.synchronize { @seen.delete(id) }
|
80
78
|
end
|
81
79
|
end
|
82
80
|
begin
|
data/lib/zold/version.rb
CHANGED
data/lib/zold/wallet.rb
CHANGED
@@ -36,7 +36,7 @@ class TestAsyncEntrance < Minitest::Test
|
|
36
36
|
def test_renders_json
|
37
37
|
FakeHome.new(log: test_log).run do |home|
|
38
38
|
Zold::AsyncEntrance.new(FakeEntrance.new, home.dir, log: test_log).start do |e|
|
39
|
-
assert_equal(
|
39
|
+
assert_equal(0, e.to_json[:queue])
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
@@ -66,8 +66,8 @@ class TestAsyncEntrance < Minitest::Test
|
|
66
66
|
wallet.sub(amount, "NOPREFIX@#{Zold::Id.new}", key)
|
67
67
|
5.times { e.push(wallet.id, IO.read(wallet.path)) }
|
68
68
|
end
|
69
|
+
assert_equal_wait(true) { basic.count >= 20 }
|
69
70
|
end
|
70
|
-
assert_equal_wait(true) { basic.count >= 20 }
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
data/test/node/test_farm.rb
CHANGED
@@ -59,6 +59,28 @@ class FarmTest < Minitest::Test
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
+
# @todo #527:30min This test takes too long. The speed should be less than
|
63
|
+
# a few milliseconds, however, if you run it a few times, you will see
|
64
|
+
# that it is over 100ms sometimes. This is way too slow. I can't understand
|
65
|
+
# what's going on. It seems that IO.read() is taking too long sometimes.
|
66
|
+
# Try to measure its time of execution in Farm.load() and you will see
|
67
|
+
# that it's usually a few microseconds, but sometimes over 200ms.
|
68
|
+
def test_reads_scores_at_high_speed
|
69
|
+
Dir.mktmpdir do |dir|
|
70
|
+
farm = Zold::Farm.new('NOPREFIX6@ffffffffffffffff', File.join(dir, 'f'), log: test_log)
|
71
|
+
farm.start('localhost', 80, threads: 4, strength: 4) do
|
72
|
+
assert_wait { !farm.best.empty? && !farm.best[0].value.zero? }
|
73
|
+
cycles = 100
|
74
|
+
speed = (0..cycles - 1).map do
|
75
|
+
start = Time.now
|
76
|
+
farm.best
|
77
|
+
Time.now - start
|
78
|
+
end.inject(&:+) / cycles
|
79
|
+
test_log.debug("Average speed is #{(speed * 1000).round(2)}ms in #{cycles} cycles")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
62
84
|
def test_makes_best_score_in_background
|
63
85
|
Dir.mktmpdir do |dir|
|
64
86
|
farm = Zold::Farm.new('NOPREFIX1@ffffffffffffffff', File.join(dir, 'f'), log: test_log)
|
data/test/test_dir_items.rb
CHANGED
@@ -25,6 +25,7 @@ require 'tmpdir'
|
|
25
25
|
require 'threads'
|
26
26
|
require_relative 'test__helper'
|
27
27
|
require_relative '../lib/zold/age'
|
28
|
+
require_relative '../lib/zold/endless'
|
28
29
|
require_relative '../lib/zold/dir_items'
|
29
30
|
|
30
31
|
# DirItems test.
|
@@ -36,7 +37,7 @@ class TestDirItems < Minitest::Test
|
|
36
37
|
Dir.mktmpdir do |dir|
|
37
38
|
file = File.join(dir, 'hey.txt')
|
38
39
|
back = Thread.start do
|
39
|
-
|
40
|
+
Endless.new('test-diritems', log: test_log).run do
|
40
41
|
Zold::DirItems.new(dir).fetch
|
41
42
|
end
|
42
43
|
end
|
data/test/test_wallet.rb
CHANGED
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.16.
|
4
|
+
version: 0.16.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-11-
|
11
|
+
date: 2018-11-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: backtrace
|
@@ -526,6 +526,7 @@ files:
|
|
526
526
|
- lib/zold/commands/taxes.rb
|
527
527
|
- lib/zold/copies.rb
|
528
528
|
- lib/zold/dir_items.rb
|
529
|
+
- lib/zold/endless.rb
|
529
530
|
- lib/zold/gem.rb
|
530
531
|
- lib/zold/head.rb
|
531
532
|
- lib/zold/hexnum.rb
|