zold 0.16.12 → 0.16.13
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/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
|