redsnapper 0.3.0 → 0.3.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.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/lib/redsnapper.rb +31 -20
  4. data/redsnapper.gemspec +3 -3
  5. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 437b104c05b11ec9161133017a941e47a7ffb346
4
- data.tar.gz: 3d573ff4757231f174467a84750d59e820b38300
3
+ metadata.gz: ad704b383d106faf8371c582c8ac01674268e8b3
4
+ data.tar.gz: ff80041ec11718c48302a367a8a7a48bc59ca654
5
5
  SHA512:
6
- metadata.gz: 0aad4e248e1e002e7d5a29910726b64939f7f1a9bfbfc330bf603e7d1de6f6777d07d0028ce47cf186d70cafebde5732b856b0cd9eb3fbdb1ea12d247ed25699
7
- data.tar.gz: 553e1c4415de048636a5fab39219da562c11e4a77afd6a8a21e40c06efa153d32ae87e0560dbb2567edb3359365e65053885bb90834f270bed3dedb7133a9058
6
+ metadata.gz: f21f67d23ddd54adeabcca421dff2ccbaf031544605a6d336cc903fc5e170a0831abe7e076532317b65831017835ad8e2de84a6b5d3413b40b0432accf60690d
7
+ data.tar.gz: 067eb80b79bd5baa06229802cfde89ef0f6b3382ac83005746929af890a47536147ab05ea25182be5d9642242355f35aed12f2fdede4f262d4be8b03cb5eca0e
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.3.1
@@ -4,7 +4,10 @@ require 'set'
4
4
 
5
5
  class RedSnapper
6
6
  TARSNAP = 'tarsnap'
7
- THREAD_POOL_SIZE = 10
7
+ THREAD_POOL_DEFAULT_SIZE = 10
8
+ EXIT_ERROR = "tarsnap: Error exit delayed from previous errors.\n"
9
+
10
+ @@output_mutex = Mutex.new
8
11
 
9
12
  class Group
10
13
  attr_reader :files, :size
@@ -24,14 +27,17 @@ class RedSnapper
24
27
  def initialize(archive, options = {})
25
28
  @archive = archive
26
29
  @options = options
27
- @thread_pool_size = options[:thread_pool_size] || THREAD_POOL_SIZE
30
+ @thread_pool = Thread.pool(options[:thread_pool_size] || THREAD_POOL_DEFAULT_SIZE)
31
+ @error = false
28
32
  end
29
33
 
30
- def files
34
+ def file_sizes
35
+ return @sizes if @sizes
36
+
31
37
  command = [ TARSNAP, '-tvf', @archive, *@options[:tarsnap_options] ]
32
38
  command.push(@options[:directory]) if @options[:directory]
33
39
 
34
- files = {}
40
+ @sizes = {}
35
41
  dirs = Set.new
36
42
 
37
43
  Open3.popen3(*command) do |_, out, _|
@@ -40,50 +46,55 @@ class RedSnapper
40
46
  if name.end_with?('/')
41
47
  dirs.add(name)
42
48
  else
43
- files[name] = size.to_i
49
+ @sizes[name] = size.to_i
44
50
  end
45
51
  end
46
52
  end
47
53
 
48
- files.each { |f, _| dirs.delete(File.dirname(f) + '/') }
49
-
50
54
  empty_dirs = dirs.clone
55
+ @sizes.each { |f, _| empty_dirs.delete(File.dirname(f) + '/') }
51
56
 
52
57
  dirs.each do |dir|
53
- components = dir.split('/')
54
- components.each_with_index do |component, i|
55
- empty_dirs.delete(components[0, i].join('/') + '/')
58
+ components = dir.split('/')[0..-2]
59
+ components.each_with_index do |_, i|
60
+ empty_dirs.delete(components[0, i + 1].join('/') + '/')
56
61
  end
57
62
  end
58
63
 
59
- empty_dirs.each { |dir| files[dir] = 0 }
64
+ empty_dirs.each { |dir| @sizes[dir] = 0 }
60
65
 
61
- files
66
+ @sizes
67
+ end
68
+
69
+ def files
70
+ @files ||= file_sizes.keys
62
71
  end
63
72
 
64
73
  def file_groups
65
- groups = (1..@thread_pool_size).map { Group.new }
66
- files.sort { |a, b| b.last <=> a.last }.each do |file|
74
+ groups = (1..@thread_pool.max).map { Group.new }
75
+ file_sizes.sort { |a, b| b.last <=> a.last }.each do |file|
67
76
  groups.sort.last.add(*file)
68
77
  end
69
78
  groups.map(&:files)
70
79
  end
71
80
 
72
81
  def run
73
- pool = Thread.pool(@thread_pool_size)
74
- mutex = Mutex.new
75
-
76
82
  file_groups.each do |chunk|
77
- pool.process do
83
+ @thread_pool.process do
78
84
  command = [ TARSNAP, '-xvf', @archive, *(@options[:tarsnap_options] + chunk) ]
79
85
  Open3.popen3(*command) do |_, _, err|
80
86
  while line = err.gets
81
- mutex.synchronize { warn line.chomp }
87
+ if line == EXIT_ERROR
88
+ @error = true
89
+ next
90
+ end
91
+ @@output_mutex.synchronize { warn line.chomp }
82
92
  end
83
93
  end
84
94
  end
85
95
  end
86
96
 
87
- pool.shutdown
97
+ @thread_pool.shutdown
98
+ @@output_mutex.synchronize { warn EXIT_ERROR } if @error
88
99
  end
89
100
  end
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: redsnapper 0.3.0 ruby lib
5
+ # stub: redsnapper 0.3.1 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "redsnapper"
9
- s.version = "0.3.0"
9
+ s.version = "0.3.1"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib"]
13
13
  s.authors = ["Scott Wheeler"]
14
- s.date = "2016-12-30"
14
+ s.date = "2016-12-31"
15
15
  s.description = "Faster extraction of large tarsnap archives using a pool of parallel tarsnap clients"
16
16
  s.email = "scott@directededge.com"
17
17
  s.executables = ["redsnapper"]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redsnapper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Wheeler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-30 00:00:00.000000000 Z
11
+ date: 2016-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thread