zold 0.14.17 → 0.14.18

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
  SHA1:
3
- metadata.gz: 8582f56181daabcedc46abc203d1943bfda757ce
4
- data.tar.gz: e90c0622d71c5982bc1b17d77ee715aa6945bf52
3
+ metadata.gz: 5ecca17ec572da83d30874c74ad40b383e22855e
4
+ data.tar.gz: 501cc2ef09710e3bd6d578d3f8cae99895ae25e8
5
5
  SHA512:
6
- metadata.gz: 34d9806bfa3b4432ceed5edec33133e0488299c9f7265bdac939aa4676f1ed7a15107487f39da8400545fe5974f23ad8cc84a77f6ff70059b1e3d1250eef117a
7
- data.tar.gz: e56681d98fd04e4b2e9eb105036b853a871f1fe0e9d214e91d4db22078bb78f1d0f3e7197313c6162e7c3e93a2c8dbe948dc4a5c7edd1f1d72343df3fa8a9ae2
6
+ metadata.gz: 584cfab45f2f97b6d5bccaee7e285d1637ca546357bb9b08e7a7e30f85789a31ca69e59ec96e72177b6c64568284e0ab982248bc25c0ada8a13ad86580c9496b
7
+ data.tar.gz: '09553f0034eee231dbba5c6d1eccd3c2d4e8e120bb70505f741d1b20f21cd7d103baeca54259c0e5bfad66b97e4b64b62ea3fb536b5eef411b9344faf83fbbfa'
data/.gitignore CHANGED
@@ -5,3 +5,5 @@ Gemfile.lock
5
5
  .bundle/
6
6
  .DS_Store
7
7
  rdoc/
8
+ .zoldata
9
+ farm
@@ -16,7 +16,7 @@ Metrics/AbcSize:
16
16
  Metrics/BlockLength:
17
17
  Max: 100
18
18
  Metrics/ClassLength:
19
- Max: 250
19
+ Max: 300
20
20
  Layout/EndOfLine:
21
21
  EnforcedStyle: lf
22
22
  Metrics/ParameterLists:
data/bin/zold CHANGED
@@ -95,6 +95,8 @@ Available commands:
95
95
  Run node at the given TCP port
96
96
  #{Rainbow('alias').green} [alias] [wallet ID]
97
97
  Set an alias for a wallet
98
+ #{Rainbow('next').green} score
99
+ Generate next score from the provided one
98
100
  #{Rainbow('score').green} [options]
99
101
  Generate score for the given host and port
100
102
  Available options:"
@@ -149,7 +151,7 @@ Available options:"
149
151
  Zold::RenameForeignWallets.new(Dir.pwd, opts['network'], log).exec
150
152
 
151
153
  wallets = Zold::Wallets.new('.')
152
- remotes = Zold::Remotes.new('./.zoldata/remotes', network: opts['network'])
154
+ remotes = Zold::Remotes.new(file: './.zoldata/remotes', network: opts['network'])
153
155
  copies = './.zoldata/copies'
154
156
 
155
157
  case command
@@ -201,6 +203,9 @@ Available options:"
201
203
  when 'score'
202
204
  require_relative '../lib/zold/commands/calculate'
203
205
  Zold::Calculate.new(log: log).run(args)
206
+ when 'next'
207
+ require_relative '../lib/zold/commands/next'
208
+ Zold::Next.new(log: log).run(args)
204
209
  else
205
210
  raise "Command '#{command}' is not supported"
206
211
  end
@@ -5,7 +5,7 @@ shopt -s expand_aliases
5
5
 
6
6
  export RUBYOPT="-W0"
7
7
 
8
- alias zold="$1 --ignore-this-stupid-option --ignore-global-config --trace --network=test --no-colors"
8
+ alias zold="$1 --ignore-this-stupid-option --halt-code=test --ignore-global-config --trace --network=test --no-colors --dump-errors"
9
9
 
10
10
  function reserve_port {
11
11
  python -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()'
@@ -13,33 +13,53 @@ function reserve_port {
13
13
 
14
14
  function wait_for_url {
15
15
  while ! curl --silent --fail $1 > /dev/null; do
16
- ((p++)) || sleep 1
16
+ ((p++)) || sleep 5
17
17
  if ((p==30)); then
18
- echo URL $1 is not available after $p seconds of waiting
19
- exit -1
18
+ echo "URL $1 is not available after $p seconds of waiting"
19
+ exit 12
20
20
  fi
21
- sleep 1
21
+ sleep 5
22
22
  done
23
23
  }
24
24
 
25
25
  function wait_for_port {
26
26
  while ! nc -z localhost $1; do
27
- ((p++)) || sleep 1
27
+ ((p++)) || sleep 5
28
28
  if ((p==30)); then
29
- echo Port $1 is not available after $p seconds of waiting
30
- exit -1
29
+ echo "Port $1 is not available after $p seconds of waiting"
30
+ exit 13
31
31
  fi
32
- sleep 1
32
+ sleep 5
33
33
  done
34
34
  }
35
35
 
36
36
  function wait_for_file {
37
37
  while [ ! -f $1 ]; do
38
- ((c++)) || sleep 1
38
+ ((c++)) || sleep 5
39
39
  if ((c==30)); then
40
- echo File $1 not found, giving up after $c seconds of waiting
41
- exit -1
40
+ echo "File $1 not found, giving up after $c seconds of waiting"
41
+ exit 14
42
42
  fi
43
- sleep 1
43
+ sleep 5
44
44
  done
45
45
  }
46
+
47
+ function halt_nodes {
48
+ for p in "$@"; do
49
+ pid=$(curl --silent "http://localhost:$p/pid?halt=test" || echo 'absent')
50
+ if [[ "${pid}" =~ ^[0-9]+$ ]]; then
51
+ while kill -0 ${pid}; do
52
+ ((c++)) || sleep 5
53
+ if ((c==30)); then
54
+ echo "Waiting for process ${pid} to die"
55
+ exit 15
56
+ fi
57
+ echo "Still waiting for process ${pid} to die, cycle no.${c}"
58
+ sleep 5
59
+ done
60
+ echo "Process ${pid} is dead!"
61
+ fi
62
+ echo "Node at TCP port ${p} stopped!"
63
+ done
64
+ }
65
+
@@ -1,3 +1,3 @@
1
1
  #!/bin/bash
2
2
 
3
- zold score --host=zold.io --port=4096 --invoice=NOSUFFIX@ffffffffffffffff --strength=2 --max=5
3
+ zold score --host=zold.io --port=4096 --invoice=CALCSCORE@ffffffffffffffff --strength=2 --max=5
@@ -4,7 +4,7 @@ function start_node {
4
4
  port=$(reserve_port)
5
5
  mkdir ${port}
6
6
  cd ${port}
7
- zold node --trace --invoice=NOPREFIX@ffffffffffffffff \
7
+ zold node --trace --invoice=DISTRWALLET@ffffffffffffffff \
8
8
  --host=localhost --port=${port} --bind-port=${port} \
9
9
  --threads=0 --routine-immediately > log.txt &
10
10
  pid=$!
@@ -18,7 +18,7 @@ function start_node {
18
18
  # don't do the TRAP for killing, the test will never end.
19
19
  first=$(start_node)
20
20
  second=$(start_node)
21
- trap "kill -9 $(cat ${first}/pid) $(cat ${second}/pid)" EXIT
21
+ trap "halt_nodes ${first} ${second}" EXIT
22
22
 
23
23
  # The first node is linked to the second one and the second one
24
24
  # is linked to the first one. The --home argument specifies their
@@ -4,11 +4,11 @@ port=$(reserve_port)
4
4
 
5
5
  mkdir server
6
6
  cd server
7
- zold node --trace --invoice=NOPREFIX@ffffffffffffffff \
7
+ zold node --trace --invoice=PUSHNPULL@ffffffffffffffff \
8
8
  --host=localhost --port=${port} --bind-port=${port} \
9
9
  --threads=0 --standalone &
10
10
  pid=$!
11
- trap "kill -9 $pid" EXIT
11
+ trap "halt_nodes ${port}" EXIT
12
12
  cd ..
13
13
 
14
14
  wait_for_port ${port}
@@ -4,9 +4,9 @@ function start_node {
4
4
  mkdir $1
5
5
  cd $1
6
6
  zold remote clean
7
- zold node $3 --nohup --nohup-command='touch restarted' --nohup-log=log \
7
+ zold node $3 --nohup --nohup-command='touch restarted' --nohup-log=log --nohup-max-cycles=0 \
8
8
  --expose-version=$2 --save-pid=pid --routine-immediately \
9
- --verbose --trace --invoice=NOPREFIX@ffffffffffffffff \
9
+ --verbose --trace --invoice=REDEPLOY@ffffffffffffffff \
10
10
  --host=localhost --port=$1 --bind-port=$1 --threads=0 > /dev/null 2>&1
11
11
  wait_for_port $1
12
12
  cat pid
@@ -20,7 +20,7 @@ low=$(reserve_port)
20
20
  secondary=$(start_node ${low} 1.1.1)
21
21
  zold remote add localhost ${high} --home=${low} --skip-ping
22
22
 
23
- trap "kill -9 ${primary} ${secondary}" EXIT
23
+ trap "halt_nodes ${high}" EXIT
24
24
 
25
25
  wait_for_file ${low}/restarted
26
26
 
@@ -6,7 +6,7 @@ zold node --trace --invoice=NOPREFIX@ffffffffffffffff \
6
6
  --host=localhost --port=${port} --bind-port=${port} \
7
7
  --threads=0 --standalone &
8
8
  pid=$!
9
- trap "kill -9 $pid" EXIT
9
+ trap "halt_nodes ${port}" EXIT
10
10
 
11
11
  wait_for_port ${port}
12
12
 
@@ -4,7 +4,7 @@ function start_node {
4
4
  port=$(reserve_port)
5
5
  mkdir ${port}
6
6
  cd ${port}
7
- zold node --trace --invoice=NOPREFIX@ffffffffffffffff \
7
+ zold node --trace --invoice=SPREADWALLETS@ffffffffffffffff \
8
8
  --host=localhost --port=${port} --bind-port=${port} \
9
9
  --threads=0 > log.txt &
10
10
  pid=$!
@@ -16,7 +16,7 @@ function start_node {
16
16
 
17
17
  first=$(start_node)
18
18
  second=$(start_node)
19
- trap "kill -9 $(cat ${first}/pid) $(cat ${second}/pid)" EXIT
19
+ trap "halt_nodes ${first} ${second}" EXIT
20
20
 
21
21
  zold --home=${first} remote clean
22
22
  zold --home=${first} remote add localhost ${second}
@@ -0,0 +1,57 @@
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 'slop'
24
+ require_relative '../log'
25
+ require_relative '../score'
26
+
27
+ # NEXT command.
28
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
29
+ # Copyright:: Copyright (c) 2018 Yegor Bugayenko
30
+ # License:: MIT
31
+ module Zold
32
+ # Calculate next score
33
+ class Next
34
+ def initialize(log: Log::Quiet.new)
35
+ @log = log
36
+ end
37
+
38
+ def run(args = [])
39
+ opts = Slop.parse(args, help: true, suppress_errors: true) do |o|
40
+ o.banner = "Usage: zold next [options] score
41
+ Available options:"
42
+ o.bool '--help', 'Print instructions'
43
+ end
44
+ if opts.help?
45
+ @log.info(opts.to_s)
46
+ return
47
+ end
48
+ calculate(opts)
49
+ end
50
+
51
+ private
52
+
53
+ def calculate(opts)
54
+ @log.info(Score.parse(opts.arguments[1]).next.to_s)
55
+ end
56
+ end
57
+ end
@@ -93,6 +93,9 @@ module Zold
93
93
  o.string '--nohup-log',
94
94
  'The file to log output into (default: zold.log)',
95
95
  default: 'zold.log'
96
+ o.string '--halt-code',
97
+ 'The value of HTTP query parameter "halt," which will cause the front-end immediate termination',
98
+ default: ''
96
99
  o.string '--save-pid',
97
100
  'The file to save process ID into right after start (only in NOHUP mode)'
98
101
  o.bool '--never-reboot',
@@ -111,6 +114,10 @@ module Zold
111
114
  "The name of the network (default: #{Wallet::MAIN_NETWORK})",
112
115
  require: true,
113
116
  default: Wallet::MAIN_NETWORK
117
+ o.integer '--nohup-max-cycles',
118
+ 'Maximum amount of nohup re-starts (-1 by default, which means forever)',
119
+ require: true,
120
+ default: -1
114
121
  o.bool '--help', 'Print instructions'
115
122
  end
116
123
  if opts.help?
@@ -129,6 +136,7 @@ module Zold
129
136
  Front.set(:version, opts['expose-version'])
130
137
  Front.set(:protocol, Zold::PROTOCOL)
131
138
  Front.set(:logging, @log.debug?)
139
+ Front.set(:halt, opts['halt-code'])
132
140
  Front.set(:home, Dir.pwd)
133
141
  @log.info("Home directory: #{Dir.pwd}")
134
142
  @log.info("Ruby version: #{RUBY_VERSION}")
@@ -145,7 +153,7 @@ module Zold
145
153
  AccessLog: []
146
154
  )
147
155
  if opts['standalone']
148
- @remotes = Remotes::Empty.new
156
+ @remotes = Zold::Remotes::Empty.new(file: '/tmp/standalone')
149
157
  @log.debug('Running in standalone mode! (will never talk to other remotes)')
150
158
  end
151
159
  Front.set(:ignore_score_weakness, opts['ignore-score-weakness'])
@@ -196,10 +204,10 @@ module Zold
196
204
  @log.info("Starting up the web front at http://#{host}:#{opts[:port]}...")
197
205
  Front.run!
198
206
  @log.info("The web front stopped at http://#{host}:#{opts[:port]}")
207
+ @log.info('Thanks for helping Zold network!')
199
208
  end
200
209
  end
201
210
  end
202
- @log.info("The node #{host}:#{opts[:port]} is shut down, thanks for helping Zold network!")
203
211
  end
204
212
 
205
213
  private
@@ -238,19 +246,26 @@ module Zold
238
246
  end
239
247
  myself = File.expand_path($PROGRAM_NAME)
240
248
  args = ARGV.delete_if { |a| a.start_with?('--nohup', '--home') }
249
+ cycle = 0
241
250
  loop do
242
251
  begin
243
252
  code = exec("#{myself} #{args.join(' ')}", nohup_log)
244
- if code != 0
245
- nohup_log.print("Let's wait for a minute, because of the failure...")
246
- sleep(60)
247
- end
253
+ raise "Exit code is #{code}" if code != 0
248
254
  exec(opts['nohup-command'], nohup_log)
249
255
  rescue StandardError => e
250
256
  nohup_log.print(Backtrace.new(e).to_s)
251
- nohup_log.print("Let's wait for a minutes, because of the exception...")
252
- sleep(60)
257
+ if cycle < opts['nohup-max-cycles']
258
+ nohup_log.print("Let's wait for a minutes, because of the exception...")
259
+ sleep(60)
260
+ end
261
+ end
262
+ next if opts['nohup-max-cycles'].negative?
263
+ cycle += 1
264
+ if cycle > opts['nohup-max-cycles']
265
+ nohup_log.print("There are no more nohup cycles left, after the cycle no.#{cycle}")
266
+ break
253
267
  end
268
+ nohup_log.print("Going for nohup cycle no.#{cycle}")
254
269
  end
255
270
  end
256
271
  Process.detach(pid)
@@ -207,10 +207,13 @@ Available options:"
207
207
  end
208
208
 
209
209
  def trim(opts)
210
- @remotes.all.each do |r|
211
- remove(r[:host], r[:port], opts) if r[:errors] > opts['tolerate']
210
+ all = @remotes.all
211
+ all.each do |r|
212
+ next if r[:errors] <= opts['tolerate']
213
+ remove(r[:host], r[:port], opts)
214
+ @log.info("#{r[:host]}:#{r[:port]} removed because of #{r[:errors]} errors (over #{opts['tolerate']})")
212
215
  end
213
- @log.info("The list of remotes trimmed, #{@remotes.all.count} nodes left there")
216
+ @log.info("The list of #{all.count} remotes trimmed, #{@remotes.all.count} nodes left there")
214
217
  end
215
218
 
216
219
  def update(opts, deep = true)
@@ -256,7 +259,7 @@ in #{(Time.now - start).round(2)}s")
256
259
  end
257
260
 
258
261
  def select(opts)
259
- selected = @remotes.all.sort_by { |r| r[:score] }.first(opts['max-nodes'])
262
+ selected = @remotes.all.sort_by { |r| r[:score] }.reverse.first(opts['max-nodes'])
260
263
  (@remotes.all - selected).each do |r|
261
264
  @remotes.remove(r[:host], r[:port])
262
265
  end
@@ -55,7 +55,6 @@ module Zold
55
55
  @threads << Thread.start do
56
56
  Thread.current.abort_on_exception = true
57
57
  Thread.current.name = r.class.name
58
- Thread.current.priority = -100
59
58
  step = 0
60
59
  while alive
61
60
  start = Time.now
@@ -78,7 +78,6 @@ module Zold
78
78
  Thread.new do
79
79
  Thread.current.abort_on_exception = true
80
80
  Thread.current.name = "f#{t}"
81
- Thread.current.priority = -100
82
81
  loop do
83
82
  VerboseThread.new(@log).run do
84
83
  cycle(host, port, strength, threads)
@@ -90,7 +89,6 @@ module Zold
90
89
  @cleanup = Thread.new do
91
90
  Thread.current.abort_on_exception = true
92
91
  Thread.current.name = 'cleanup'
93
- Thread.current.priority = -100
94
92
  while alive
95
93
  sleep(60) unless strength == 1 # which will only happen in tests
96
94
  VerboseThread.new(@log).run do
@@ -147,6 +145,9 @@ module Zold
147
145
  return unless s.strength >= strength
148
146
  Thread.current.name = s.to_mnemo
149
147
  save(threads, [s.next])
148
+ # score = Score.parse(`ruby #{File.join(File.dirname(__FILE__), '../../../bin/zold')} next "#{s}"`)
149
+ # @log.debug("New score discovered: #{score}")
150
+ # save(threads, [score])
150
151
  cleanup(host, port, strength, threads)
151
152
  end
152
153
 
@@ -49,6 +49,7 @@ module Zold
49
49
  set :lock, false
50
50
  set :show_exceptions, false
51
51
  set :server, 'webrick'
52
+ set :halt, '' # to be injected at node.rb
52
53
  set :dump_errors, false # to be injected at node.rb
53
54
  set :version, VERSION # to be injected at node.rb
54
55
  set :protocol, PROTOCOL # to be injected at node.rb
@@ -69,6 +70,10 @@ module Zold
69
70
  use Rack::Deflater
70
71
 
71
72
  before do
73
+ if !settings.halt.empty? && params[:halt] && params[:halt] == settings.halt
74
+ settings.log.error('Halt signal received, shutting the front end down...')
75
+ Front.stop!
76
+ end
72
77
  check_header(Http::NETWORK_HEADER) do |header|
73
78
  if header != settings.network
74
79
  raise "Network name mismatch at #{request.url}, #{request.ip} is in '#{header}', \
@@ -119,6 +124,11 @@ while #{settings.address} is in '#{settings.network}'"
119
124
  settings.version
120
125
  end
121
126
 
127
+ get '/pid' do
128
+ content_type 'text/plain'
129
+ Process.pid.to_s
130
+ end
131
+
122
132
  get '/score' do
123
133
  content_type 'text/plain'
124
134
  score.to_s
@@ -143,6 +153,7 @@ while #{settings.address} is in '#{settings.network}'"
143
153
  score: score.to_h,
144
154
  pid: Process.pid,
145
155
  cpus: Concurrent.processor_count,
156
+ platform: RUBY_PLATFORM,
146
157
  uptime: `uptime`.strip,
147
158
  threads: "#{Thread.list.select { |t| t.status == 'run' }.count}/#{Thread.list.count}",
148
159
  wallets: settings.wallets.all.count,