mogilefs-client 3.7.1 → 3.8.0

Sign up to get free protection for your applications and to get access to all the features.
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)