mogilefs-client 3.7.1 → 3.8.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 65d3ada1142a27870a3926eeae7d15a13d28b016
4
+ data.tar.gz: 7ef65f2858cb0a130cbb7c0200946a7df05bf701
5
+ SHA512:
6
+ metadata.gz: edecf8b75e5f3e218e63383c79da8ceaab6daed1890c3d51c0ca418936c30e6a613eb187ae5258137570eee8d649a612fcbaaf0cc606baa4165a817f146a681f
7
+ data.tar.gz: b9448f892913e8104c611badaf368e22acaa6faf60c70abf729200a6c0725efe2657a13498aeeb64b11b4701a62caa7f1f547eefff4c0652834745380dd04e8e
data/.document CHANGED
@@ -1,6 +1,5 @@
1
1
  NEWS
2
2
  History
3
- ChangeLog
4
3
  LICENSE
5
4
  README
6
5
  HACKING
data/.gitignore CHANGED
@@ -2,8 +2,8 @@
2
2
  /doc
3
3
  /.config
4
4
  /InstalledFiles
5
- /ChangeLog
6
- /NEWS
5
+ /NEWS*
7
6
  /LATEST
7
+ /GIT-VERSION-FILE
8
+ /.manifest
8
9
  /lib/mogilefs/version.rb
9
- /Manifest.txt
@@ -3,3 +3,5 @@ cgit_url: http://bogomips.org/mogilefs-client.git
3
3
  git_url: git://bogomips.org/mogilefs-client.git
4
4
  rdoc_url: http://bogomips.org/mogilefs-client
5
5
  changelog_start: v1.2.1
6
+ private_email: e@80x24.org
7
+ public_email: mogilefs-client-public@bogomips.org
data/GIT-VERSION-GEN CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
  CONSTANT = "MogileFS::VERSION"
3
3
  RVF = "lib/mogilefs/version.rb"
4
- DEF_VER = "v3.7.1"
4
+ GVF = "GIT-VERSION-FILE"
5
+ DEF_VER = "v3.8.0"
5
6
  vn = DEF_VER
6
7
 
7
8
  # First see if there is a version file (included in release tarballs),
@@ -20,9 +21,19 @@ if File.exist?(".git")
20
21
  end
21
22
 
22
23
  vn = vn.sub!(/\Av/, "")
23
- new_ruby_version = "#{CONSTANT} = '#{vn}'\n"
24
+ new_ruby_version = "#{CONSTANT} = '#{vn}' # :nodoc:\n"
24
25
  cur_ruby_version = File.read(RVF) rescue nil
25
26
  if new_ruby_version != cur_ruby_version
26
27
  File.open(RVF, "w") { |fp| fp.write(new_ruby_version) }
27
28
  end
29
+ File.chmod(0644, RVF)
30
+
31
+ # generate the makefile snippet
32
+ new_make_version = "GIT_VERSION = #{vn}\n"
33
+ cur_make_version = File.read(GVF) rescue nil
34
+ if new_make_version != cur_make_version
35
+ File.open(GVF, "w") { |fp| fp.write(new_make_version) }
36
+ end
37
+ File.chmod(0644, GVF)
38
+
28
39
  puts vn if $0 == __FILE__
data/GNUmakefile CHANGED
@@ -1,90 +1,16 @@
1
- # use GNU Make to run tests in parallel, and without depending on Rubygems
2
- all:: test
1
+ all::
3
2
  RSYNC_DEST := bogomips.org:/srv/bogomips/mogilefs-client
4
- git_version_gen := $(shell ./GIT-VERSION-GEN)
3
+ rfpackage := mogilefs-client
4
+ pkg_extra += lib/mogilefs/version.rb
5
5
 
6
- T := $(wildcard test/test*.rb)
7
- TO := $(subst .rb,.log,$(T))
6
+ ex := $(shell git ls-files examples/)
7
+ doc_ex := $(addprefix doc/, $(ex))
8
8
 
9
- test: $(T)
10
- @cat $(TO) | ruby test/aggregate.rb
11
- @$(RM) $(TO)
12
- clean:
13
- $(RM) $(TO) $(addsuffix +,$(TO))
9
+ $(doc_ex): $(ex)
10
+ mkdir -p $(@D)
11
+ install -m 644 $< $@
12
+ -touch -r $< $@ # GNU
14
13
 
15
-
16
- ifndef V
17
- quiet_pre = @echo '* $@';
18
- quiet_post = >$(t) 2>&1
19
- else
20
- # we can't rely on -o pipefail outside of bash 3+,
21
- # so we use a stamp file to indicate success and
22
- # have rm fail if the stamp didn't get created
23
- stamp = $@$(log_suffix).ok
24
- quiet_pre = @echo $(ruby) $@ $(TEST_OPTS); ! test -f $(stamp) && (
25
- quiet_post = && > $(stamp) )>&2 | tee $(t); rm $(stamp) 2>/dev/null
26
- endif
27
- ruby = ruby
28
- run_test = $(quiet_pre) setsid $(ruby) -w $@ $(TEST_OPTS) $(quiet_post) || \
29
- (sed "s,^,$(extra): ," >&2 < $(t); exit 1)
30
-
31
- $(T): t = $(subst .rb,.log,$@)
32
- $(T): export RUBYLIB := $(CURDIR)/lib:$(RUBYLIB)
33
- $(T):
34
- $(run_test)
35
-
36
- RUBY_VERSION_FILE = lib/mogilefs/version.rb
37
- package:
38
- git diff --exit-code HEAD^0
39
- $(RM) -r pkg/
40
- rake fix_perms
41
- rake package
42
-
43
- libs := $(wildcard lib/*.rb lib/*/*.rb)
44
- flay_flags =
45
- flog_flags =
46
- flay: $(libs)
47
- flay $(flay_flags) $^
48
- flog: $(libs)
49
- flog $(flog_flags) $^
50
- .PHONY: $(T)
51
-
52
- check-warnings:
53
- @(for i in $$(git ls-files '*.rb'| grep -v '^setup\.rb$$'); \
54
- do ruby -d -W2 -c $$i; done) | grep -v '^Syntax OK$$' || :
55
- RSYNC = rsync
56
- WRONGDOC = wrongdoc
57
-
58
- doc:: .document .wrongdoc.yml $(pkg_extra)
59
- -find lib -type f -name '*.rbc' -exec rm -f '{}' ';'
60
- $(RM) -r doc
61
- $(WRONGDOC) all
62
- install -m644 $(shell LC_ALL=C grep '^[A-Z]' .document) doc/
63
- cd doc && \
64
- ln -s README README.txt && \
65
- ln -s README.html README_txt.html && \
66
- ln -s LICENSE LICENSE.txt && \
67
- ln -s LICENSE.html LICENSE_txt.html && \
68
- ln -s History History.txt && \
69
- ln -s History.html History_txt.html
70
-
71
- # Create gzip variants of the same timestamp as the original so nginx
72
- # "gzip_static on" can serve the gzipped versions directly.
73
- doc_gz: docs = $(shell find doc -type f ! -regex '^.*\.\(gif\|jpg\|png\|gz\)$$')
74
- doc_gz:
75
- for i in $(docs); do \
76
- gzip --rsyncable -9 < $$i > $$i.gz; touch -r $$i $$i.gz; done
77
-
78
- # this requires GNU coreutils variants
79
- ifneq ($(RSYNC_DEST),)
80
- publish_doc:
81
- -git set-file-times
82
- $(MAKE) doc
83
- find doc/images -type f | \
84
- TZ=UTC xargs touch -d '1970-01-01 00:00:06' doc/rdoc.css
85
- $(MAKE) doc_gz
86
- $(RSYNC) -av doc/ $(RSYNC_DEST)/
87
- git ls-files | xargs touch
88
- endif
89
-
90
- .PHONY: doc .FORCE-GIT-VERSION-FILE
14
+ include pkg.mk
15
+ doc::
16
+ $(MAKE) $(doc_ex)
data/README CHANGED
@@ -9,8 +9,10 @@ MogileFS instance.
9
9
 
10
10
  rdoc :: http://bogomips.org/mogilefs-client
11
11
  mogilefs :: http://mogilefs.org/
12
- list :: mailto:mogile@googlegroups.com
13
- email :: mailto:normalperson@yhbt.net
12
+ list :: mailto:mogilefs-client-public@bogomips.org
13
+ list-cc :: mailto:mogile@googlegroups.com
14
+ list-archive :: http://bogomips.org/mogilefs-client-public
15
+ email :: mailto:e@80x24.org
14
16
  repo :: git://bogomips.org/mogilefs-client.git
15
17
  cgit :: http://bogomips.org/mogilefs-client.git
16
18
  gitweb :: http://repo.or.cz/w/ruby-mogilefs-client.git
@@ -35,15 +37,23 @@ See MogileFS::MogileFS
35
37
  == Contact
36
38
 
37
39
  Feedback (bug reports, user/development discussion, patches, pull
38
- requests) are greatly appreciated and handled via email. We currently
39
- piggy-back onto the public MogileFS
40
- mailing list at mailto:mogile@googlegroups.com for feedback.
40
+ requests) are greatly appreciated and handled via email to a public
41
+ inbox. HTML email is considered spam and discarded. No subscription
42
+ is required or available to post:
41
43
 
42
- If you do not want to deal with the corporate host of the MogileFS
43
- mailing list, or if you wish to keep your issue secret, feel free to
44
- email Eric Wong at mailto:normalperson@yhbt.net.
44
+ mogilefs-client-public@bogomips.org
45
45
 
46
- Do not expect Eric Wong to read HTML mail under any circumstances.
46
+ List archives: http://bogomips.org/mogilefs-client-public/
47
+
48
+ We may also piggy-back onto the public MogileFS mailing list at
49
+ mogile@googlegroups.com for feedback (subscription required,
50
+ unfortunately)
51
+
52
+ If you wish to keep your issue secret, feel free to email the author at:
53
+
54
+ e@80x24.org
55
+
56
+ Do not expect us to read HTML mail under any circumstances.
47
57
 
48
58
  == WARNING!
49
59
 
data/TODO CHANGED
@@ -3,8 +3,4 @@ private email (mailto:normalperson@yhbt.net) greatly appreciated!
3
3
 
4
4
  * MogileFS::Admin needs to be fleshed out
5
5
 
6
- * optional Cool.io support
7
-
8
- * optional EventMachine support
9
-
10
6
  * manpage for "mog"
@@ -0,0 +1,245 @@
1
+ #!/usr/bin/env ruby
2
+ usage = <<EOF
3
+ Usage: #$0 SRC_TRACKER_LIST/SRC_DOMAIN DST_TRACKER_LIST/DST_DOMAIN"
4
+ EOF
5
+ Thread.abort_on_exception = $stdout.sync = $stderr.sync = true
6
+ require 'uri'
7
+ require 'optparse'
8
+ require 'mogilefs'
9
+ require 'thread'
10
+ @verbose = 0
11
+ copy_jobs = 1
12
+ jobs = 1
13
+ keep = nil
14
+ @dryrun = false
15
+ opts = {}
16
+ prefix = ""
17
+ src_class = dst_class = nil
18
+ src_maxlen = nil
19
+ exit_ok = true
20
+ after = nil
21
+ clobber_nsum = false
22
+
23
+ ARGV.options do |x|
24
+ x.banner = usage.strip
25
+ x.separator ''
26
+ x.on('-j', '--metadata-jobs JOBS', Integer,
27
+ 'Number of metadata jobs to run in parallel') { |n|
28
+ jobs = n
29
+ }
30
+ x.on('-J', '--copy-jobs JOBS', Integer,
31
+ 'Number of copy jobs to run in parallel') { |n|
32
+ copy_jobs = n
33
+ }
34
+
35
+ x.on('-h', '--help', 'Show this help message.') { puts x; exit }
36
+ %w(get_file_data_timeout new_file_max_time fail_timeout timeout).each do |t|
37
+ x.on("--#{t.tr('_', '-')} SECONDS", Integer) { |n| opts[t.to_sym] = n }
38
+ end
39
+ x.on('-v', '--verbose') { @verbose += 1 }
40
+ x.on('-d', '--delete') do
41
+ begin
42
+ require 'gdbm'
43
+ require 'tempfile'
44
+ tmp = Tempfile.new(%w(mog-sync-keep .gdbm))
45
+ at_exit { tmp.close! }
46
+ keep = GDBM.new(tmp.path)
47
+ rescue LoadError
48
+ warn "gdbm extension recommended for --delete: #{e.message} (#{e.class})"
49
+ keep = {}
50
+ end
51
+ end
52
+ x.on('-n', '--dry-run') { @dryrun = opts[:readonly] = true }
53
+ x.on('-p', '--prefix STRING') { |s| prefix = s }
54
+ x.on('--src-class STRING') { |s| src_class = s }
55
+ x.on('--dst-class STRING') { |s| dst_class = s }
56
+ x.on('--after STRING') { |s| after = s }
57
+ x.on('--max-size STRING') { |s|
58
+ mult = 1
59
+ if s.sub!(/-1\z/, "")
60
+ off = -1
61
+ elsif s.sub!(/\+1\z/, "")
62
+ off = 1
63
+ else
64
+ off = 0
65
+ end
66
+ {
67
+ /(?:K|KiB)\z/i => 1024,
68
+ /(?:M|MiB)\z/i => 1024 ** 2,
69
+ /(?:G|GiB)\z/i => 1024 ** 3,
70
+ /KB\z/i => 1000,
71
+ /MB\z/i => 1000 ** 2,
72
+ /GB/i => 1000 ** 3,
73
+ }.each do |re, m|
74
+ if s.sub!(re, "")
75
+ mult = m
76
+ break
77
+ end
78
+ end
79
+ src_maxlen = (s.to_i * mult) + off
80
+ }
81
+ x.on('-F', '--clobber-missing-checksum') { clobber_nsum = true }
82
+ x.parse!
83
+ end
84
+
85
+ @verbose = 1 if @verbose == 0 && @dryrun
86
+ ARGV.size == 2 or abort "Usage: #{usage}"
87
+ src_spec, dst_spec = ARGV
88
+ src_opts = opts.merge(readonly: true)
89
+
90
+ def client_for(str, opts = {})
91
+ trackers, domain = str.split('/', 2)
92
+ opts[:hosts] = trackers.split(/,/)
93
+ opts[:domain] = domain
94
+ MogileFS::MogileFS.new(opts)
95
+ end
96
+
97
+ # atomic for pipes/O_APPEND:
98
+ def warn(m); $stderr.syswrite("#{m}\n"); end
99
+ def echo(m); $stdout.syswrite("#{m}\n"); end
100
+
101
+ def copy(job_id, reason, src, dst, src_info, dst_info, dst_class)
102
+ key = src_info["key"]
103
+ length = src_info["length"]
104
+ unless @dryrun
105
+ opts = {
106
+ largefile: true,
107
+ class: dst_class || src_info["class"],
108
+ content_length: length,
109
+ }
110
+
111
+ # FIXME: test/support non-MD5 checksums
112
+ if /\AMD5:([a-fA-F0-9]{32})\z/ =~ src_info["checksum"]
113
+ md5 = [ $1 ].pack("H*")
114
+ opts[:content_md5] = [ md5 ].pack('m0').chomp
115
+ end
116
+ if @verbose > 1
117
+ echo "new_file(#{key}, #{opts.inspect})"
118
+ end
119
+ dst.new_file(key, opts) do |dst_io|
120
+ src.get_file_data(key, dst_io)
121
+ end
122
+ end
123
+ if @verbose > 0
124
+ echo("#{reason} #{key}")
125
+ if @verbose > 1 && dst_info
126
+ echo "I[#{job_id}] before #{dst_info.inspect}"
127
+ echo "I[#{job_id}] after #{src_info.inspect}"
128
+ end
129
+ end
130
+ Thread.current[:mog_sync_xfer] += length
131
+ rescue => e
132
+ warn "E[#{job_id}] #{e.message} (#{e.class}) (src=#{key})"
133
+ e.backtrace { |l| warn "E[#{job_id}] #{l}" }
134
+ end
135
+
136
+ copy_queue = SizedQueue.new(copy_jobs * 8)
137
+ copiers = copy_jobs.times.map do |i|
138
+ Thread.new(i) do |job_id|
139
+ Thread.current[:mog_sync_xfer] = 0
140
+ while copy_job = copy_queue.pop
141
+ copy(job_id, *copy_job)
142
+ end
143
+ end
144
+ end
145
+
146
+ queue = SizedQueue.new(jobs * 8)
147
+ consumers = jobs.times.map do |i|
148
+ Thread.new(i) do |job_id|
149
+ dst = client_for(dst_spec, opts)
150
+ src = client_for(src_spec, src_opts)
151
+ begin
152
+ key = queue.pop or break
153
+ src_info = src.file_info(key)
154
+ next if src_class && src_class != src_info["class"]
155
+ src_checksum = src_info["checksum"]
156
+ next if src_maxlen && src_info["length"] > src_maxlen
157
+
158
+ begin
159
+ # this may raise UnknownKeyError
160
+ dst_info = dst.file_info(key)
161
+
162
+ dst_checksum = dst_info["checksum"]
163
+
164
+ # maybe we need to wait for fsck to finish:
165
+ if dst_checksum == "MISSING"
166
+ warn "destination checksum broken #{dst_info.inspect} (skipped)"
167
+ next unless clobber_nsum
168
+ end
169
+
170
+ # tell user to fix source
171
+ if src_checksum == "MISSING"
172
+ warn "source checksum broken #{src_info.inspect} (skipped)"
173
+ exit_ok = false
174
+ next
175
+ end
176
+
177
+ next if dst_checksum == src_checksum
178
+ reason = "M"
179
+ rescue MogileFS::Backend::UnknownKeyError # new file
180
+ dst_info = nil
181
+ # tell user to fix source
182
+ if src_checksum == "MISSING"
183
+ warn "source checksum broken #{src_info.inspect} (copying)"
184
+ exit_ok = false
185
+ end
186
+ reason = "A"
187
+ end
188
+ copy_queue << [ reason, src, dst, src_info, dst_info, dst_class ]
189
+ rescue => e
190
+ warn "E[#{job_id}] #{e.message} (#{e.class}) (src=#{key})"
191
+ e.backtrace { |l| warn "E[#{job_id}] #{l}" }
192
+ end while true
193
+ end
194
+ end
195
+
196
+ # producer feeds consumers
197
+ begin
198
+ main_src = client_for(src_spec, src_opts)
199
+ main_src.each_key(prefix, after: after) do |key|
200
+ keep[key] = "1" if keep
201
+ queue << key
202
+ end
203
+ rescue => e
204
+ exit_ok = false
205
+ warn "Aborting due to source error: #{e.message} (#{e.class})"
206
+ e.backtrace { |l| warn "#{l}" }
207
+ end
208
+
209
+ # terminate producer threads
210
+ Thread.new { consumers.each { queue << nil } }
211
+ consumers.each { |t| t.join }
212
+ Thread.new { copiers.each { copy_queue << nil } }
213
+ copiers.each { |t| t.join }
214
+ bytes_sent = copiers.inject(0) { |sent,t| sent += t[:mog_sync_xfer] }
215
+ bytes_deleted = 0
216
+
217
+ # delete is single-threaded, it is not I/O-bound and
218
+ # we can pipeline in the future
219
+ if keep && exit_ok
220
+ queue = SizedQueue.new(8)
221
+ deleter = Thread.new do
222
+ dst = client_for(dst_spec, opts)
223
+ while key = queue.pop
224
+ begin
225
+ dst.delete(key) unless @dryrun
226
+ echo "D #{key}"
227
+ rescue MogileFS::Backend::UnknownKeyError
228
+ warn "#{key} disappeared before we could delete it"
229
+ end
230
+ end
231
+ end
232
+ main_dst = client_for(dst_spec, opts)
233
+ main_dst.each_file_info(prefix, after: after) do |info|
234
+ key = info["key"]
235
+ next if keep.include?(key)
236
+ queue << key
237
+ bytes_deleted += info["length"]
238
+ end
239
+ queue << nil # terminate
240
+ deleter.join
241
+ end
242
+ if @verbose
243
+ echo "wrote #{bytes_sent} bytes, removed #{bytes_deleted} bytes"
244
+ end
245
+ exit(exit_ok)