regurgitator 0.0.0 → 0.1.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.
data/ChangeLog CHANGED
@@ -1,5 +1,69 @@
1
1
  ChangeLog from http://bogomips.org/regurgitator.git
2
2
 
3
+ commit 84e48c63074049f32660672b5a3c195d12dc3896
4
+ Author: Eric Wong <normalperson@yhbt.net>
5
+ Date: Fri Nov 11 08:46:12 2011 +0000
6
+
7
+ regurgitator 0.1.0
8
+
9
+ * local_file: support HTTP Range: requests
10
+ * minor code cleanups
11
+ * update/fix install dependencies (include rpatricia)
12
+
13
+ commit 341b4d3198013893ae9929d588cfde73fa39b2ee
14
+ Author: Eric Wong <e@yhbt.net>
15
+ Date: Fri Nov 11 08:33:40 2011 +0000
16
+
17
+ local_file: support HTTP Range: requests
18
+
19
+ This should give local users Range: functionality since most
20
+ HTTP servers used for MogileFS storage support Range:, too.
21
+ For requests that require proxying back to the HTTP server,
22
+ this we've always forwarded Range: requests and Content-Range:
23
+ responses as-is in a completely agnostic manner.
24
+
25
+ commit a898550de8398fafef9690f29568fffe351df68b
26
+ Author: Eric Wong <normalperson@yhbt.net>
27
+ Date: Fri Nov 11 08:22:58 2011 +0000
28
+
29
+ bump dependencies
30
+
31
+ This forces newer kgio and newer http_spew on people, and
32
+ we'll need the latest rack for Range: parsing.
33
+
34
+ commit 6cb4d49092eceee6720a702ca51f96851711b612
35
+ Author: Eric Wong <normalperson@yhbt.net>
36
+ Date: Fri Oct 21 17:41:03 2011 -0700
37
+
38
+ use raise instead of abort in case we hit bugs
39
+
40
+ These should probably nuke the process, but we'll be nice
41
+ and raise instead since we shouldn't cause data corruption.
42
+
43
+ commit 70f8be5607ecdf087e20c0f539e6cac9c8b6bc16
44
+ Author: Eric Wong <normalperson@yhbt.net>
45
+ Date: Fri Jun 24 18:00:01 2011 -0700
46
+
47
+ test_local: use Dir.mktmpdir
48
+
49
+ The "tmpdir" module in the standhas a handy method for creating tmpdirs
50
+
51
+ commit 752fdf60e8ac560d07a0e2f7d3ee58f075c620b9
52
+ Author: Eric Wong <normalperson@yhbt.net>
53
+ Date: Fri Jun 24 17:56:38 2011 -0700
54
+
55
+ less initialize/super magic
56
+
57
+ It's making things too hard to keep track of
58
+
59
+ commit 7d826aae4753eb9eeca3467accb2c13eabd4a8eb
60
+ Author: Eric Wong <normalperson@yhbt.net>
61
+ Date: Wed May 18 16:38:51 2011 -0700
62
+
63
+ gemspec: add rpatricia dependency
64
+
65
+ Not everybody has this gem installed by default :x
66
+
3
67
  commit 0104cfec9974cc65d79ce614ab37ba3fbd672b11
4
68
  Author: Eric Wong <normalperson@yhbt.net>
5
69
  Date: Tue May 10 15:09:50 2011 -0700
data/GIT-VERSION-FILE CHANGED
@@ -1 +1 @@
1
- GIT_VERSION = 0.0.0
1
+ GIT_VERSION = 0.1.0
data/GIT-VERSION-GEN CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/bin/sh
2
2
 
3
3
  GVF=GIT-VERSION-FILE
4
- DEF_VER=v0.0.0.GIT
4
+ DEF_VER=v0.1.0.GIT
5
5
 
6
6
  LF='
7
7
  '
data/LATEST CHANGED
@@ -1 +1,6 @@
1
- Currently unreleased
1
+ === regurgitator 0.1.0 / 2011-11-11 08:47 UTC
2
+
3
+ * local_file: support HTTP Range: requests
4
+ * minor code cleanups
5
+ * update/fix install dependencies (include rpatricia)
6
+
data/NEWS CHANGED
@@ -1 +1,6 @@
1
- No news yet.
1
+ === regurgitator 0.1.0 / 2011-11-11 08:47 UTC
2
+
3
+ * local_file: support HTTP Range: requests
4
+ * minor code cleanups
5
+ * update/fix install dependencies (include rpatricia)
6
+
@@ -14,19 +14,15 @@ module Regurgitator::Device
14
14
  DEVICES_ON = 'SELECT devid FROM file_on WHERE fid = ?'
15
15
  # :startdoc:
16
16
 
17
- def initialize(*args) # :nodoc:
18
- super
19
- init_device_ivars
20
- end
21
-
22
- def init_device_ivars
17
+ def device_init
18
+ server_settings_init
23
19
  @device_cache_mtime = Time.at(0)
24
20
  @device_cache = nil
25
21
  @device_cache_lock = Mutex.new
26
22
  end
27
23
 
28
24
  def self.extended(obj)
29
- obj.init_device_ivars
25
+ obj.device_init
30
26
  end
31
27
 
32
28
  def device_uri_pair!(opts, get_port)
@@ -4,8 +4,7 @@ module Regurgitator::Domain
4
4
 
5
5
  REFRESH_DOMAIN = 'SELECT dmid,namespace FROM domain' # :nodoc:
6
6
 
7
- def initialize(*args) # :nodoc:
8
- super
7
+ def domain_init
9
8
  @domain_lock = Mutex.new
10
9
  @domain_cache_mtime = Time.at(0)
11
10
  @domain_cache = nil
@@ -27,7 +27,7 @@ class Regurgitator::DomainHost
27
27
  raise TypeError, ":suffix must be a String or Regexp #{suffix.inspect}"
28
28
  end
29
29
  @domain_regexp = suffix
30
- super(app, opts[:db])
30
+ endpoint_init(app, opts[:db])
31
31
  end
32
32
 
33
33
  def call(env) # :nodoc:
@@ -28,6 +28,6 @@ class Regurgitator::DomainPath
28
28
  end
29
29
 
30
30
  def initialize(app, db) # :nodoc:
31
- super(app, Hash === db ? db[:db] : db)
31
+ endpoint_init(app, Hash === db ? db[:db] : db)
32
32
  end
33
33
  end
@@ -7,10 +7,10 @@ module Regurgitator::Endpoint
7
7
 
8
8
  REPROXY_KEY = Regurgitator::REPROXY_KEY # :nodoc:
9
9
 
10
- def initialize(app, db)
10
+ def endpoint_init(app, db)
11
11
  @app = app
12
12
  @db = db
13
- super
13
+ file_info_init
14
14
  end
15
15
 
16
16
  def best_addr(env)
@@ -87,7 +87,7 @@ module Regurgitator::Endpoint
87
87
  body.close if body.respond_to?(:close)
88
88
  return [ status, headers, [] ]
89
89
  else
90
- abort "Unexpected REQUEST_METHOD=#{env['REQUEST_METHOD']}"
90
+ raise "BUG: Unexpected REQUEST_METHOD=#{env['REQUEST_METHOD']}"
91
91
  end
92
92
  rescue Regurgitator::NoDevices
93
93
  retry unless zone_uris.empty?
@@ -5,6 +5,11 @@ module Regurgitator::FileInfo
5
5
 
6
6
  # :stopdoc:
7
7
  FILE_INFO = 'SELECT fid,length FROM file WHERE dmid = ? AND dkey = ? LIMIT 1'
8
+
9
+ def file_info_init
10
+ domain_init
11
+ device_init
12
+ end
8
13
  # :startdoc:
9
14
 
10
15
  # returns a hash with file information and URIs for accessing the file:
@@ -55,7 +55,7 @@ module Regurgitator::Local
55
55
  Regurgitator::Local.include?(uri.host) or return
56
56
  (roots = STORE_PATHS[uri.port]).empty? and return
57
57
  uri.path =~ %r{\A/(dev\d+)/} or
58
- abort "BUG: path needs to match '\\A/dev\d+/' (#{uri})"
58
+ raise "BUG: path needs to match '\\A/dev\d+/' (#{uri})"
59
59
  devN = $1
60
60
  rv = nil
61
61
  roots.each do |root, dev_dirs|
@@ -18,12 +18,30 @@ class Regurgitator::LocalFile
18
18
  if modified_since = env["HTTP_IF_MODIFIED_SINCE"]
19
19
  modified_since?(modified_since, stat) or return
20
20
  end
21
+ size = stat.size
22
+
23
+ headers = {
24
+ "Content-Type" => "application/octet-stream", # always ".fid"
25
+ "Content-Length" => size.to_s,
26
+ "Last-Modified" => stat.mtime.httpdate,
27
+ "Accept-Ranges" => "bytes",
28
+ }
29
+ @response = [ 200, headers ]
30
+
31
+ ranges = Rack::Utils.byte_ranges(env, size)
32
+ if nil == ranges || ranges.size > 1
33
+ @range = nil
34
+ elsif @range = ranges[0]
35
+ @response[0] = 206
36
+ headers["Content-Range"] = "bytes #{@range.begin}-#{@range.end}/#{size}"
37
+ headers["Content-Length"] = (@range.end - @range.begin + 1).to_s
38
+ else
39
+ @response[0] = 416
40
+ headers["Content-Range"] = "bytes */#{size}"
41
+ @response << []
42
+ return
43
+ end
21
44
 
22
- @response = [ 200, {
23
- "Content-Type" => "application/octet-stream", # always ".fid"
24
- "Content-Length" => stat.size.to_s,
25
- "Last-Modified" => stat.mtime.httpdate,
26
- } ]
27
45
  case env["REQUEST_METHOD"]
28
46
  when "GET"
29
47
  @to_path, @uri = path, uri
@@ -31,17 +49,27 @@ class Regurgitator::LocalFile
31
49
  when "HEAD"
32
50
  @response << []
33
51
  else
34
- abort "Unexpected REQUEST_METHOD=#{env['REQUEST_METHOD']}"
52
+ raise "BUG: Unexpected REQUEST_METHOD=#{env['REQUEST_METHOD']}"
35
53
  end
36
54
  end
37
55
 
38
56
  # normal Rack HTTP server endpoint, used if the server can't handle
39
57
  # +to_path+
40
58
  def each
41
- buf = ""
42
59
  File.open(@to_path) do |fp|
43
- while fp.read(0x4000, buf)
44
- yield buf
60
+ buf = ""
61
+ max = 0x4000
62
+ if @range
63
+ fp.seek(@range.begin)
64
+ len = @range.end - @range.begin + 1
65
+ while len > 0 && fp.read(len > max ? max : len, buf)
66
+ len -= buf.size
67
+ yield buf
68
+ end
69
+ else
70
+ while fp.read(0x4000, buf)
71
+ yield buf
72
+ end
45
73
  end
46
74
  end
47
75
  end
@@ -19,7 +19,7 @@ class Regurgitator::OneDomain
19
19
 
20
20
  def initialize(app, opts) # :nodoc:
21
21
  @domain = opts[:domain]
22
- super(app, opts[:db])
22
+ endpoint_init(app, opts[:db])
23
23
  end
24
24
 
25
25
  def call(env) # :nodoc:
@@ -6,19 +6,14 @@ module Regurgitator::ServerSettings
6
6
  SETTINGS_LOOKUP = 'SELECT value FROM server_settings WHERE field = ? LIMIT 1'
7
7
  # :startdoc:
8
8
 
9
- def initialize(*args) # :nodoc:
10
- super
11
- init_zone_ivars
12
- end
13
-
14
- def init_zone_ivars
9
+ def server_settings_init
15
10
  @zone_cache_mtime = Time.at(0)
16
11
  @zone_cache = nil
17
12
  @zone_cache_lock = Mutex.new
18
13
  end
19
14
 
20
15
  def self.extended(obj)
21
- obj.init_zone_ivars
16
+ obj.server_settings_init
22
17
  end
23
18
 
24
19
  def refresh_zone(force = false) # :nodoc:
data/regurgitator.gemspec CHANGED
@@ -21,10 +21,11 @@ Gem::Specification.new do |s|
21
21
  s.rubyforge_project = %q{rainbows}
22
22
  s.test_files = Dir["test/test_*.rb"]
23
23
 
24
- s.add_dependency("rack", ["~> 1.2"])
25
- s.add_dependency("sequel", ["~> 3.23"])
26
- s.add_dependency("http_spew", ["~> 0.1"])
24
+ s.add_dependency("rack", ["~> 1.3"])
25
+ s.add_dependency("sequel", ["~> 3.29"])
26
+ s.add_dependency("http_spew", ["~> 0.4"])
27
+ s.add_dependency("rpatricia", ["~> 0.08"])
27
28
 
28
- s.add_development_dependency('wrongdoc', "~> 1.5")
29
+ s.add_development_dependency('wrongdoc', "~> 1.6")
29
30
  # s.licenses = %w(GPL2 GPL3) # accessor not compatible with older RubyGems
30
31
  end
data/test/test_local.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require "test/unit"
2
2
  require "regurgitator"
3
- require "tempfile"
3
+ require "tmpdir"
4
4
  require "fileutils"
5
5
 
6
6
  class TestLocal < Test::Unit::TestCase
@@ -16,10 +16,7 @@ class TestLocal < Test::Unit::TestCase
16
16
  @local_addrs = Regurgitator::Local.instance_variable_get(:@local_addrs)
17
17
  @local_addrs["127.0.0.1"] = true if @local_addrs.empty?
18
18
  @addr = @local_addrs.keys.first
19
- tmp = Tempfile.new('test_local')
20
- @tmpdir = tmp.path
21
- tmp.close!
22
- Dir.mkdir(@tmpdir)
19
+ @tmpdir = Dir.mktmpdir
23
20
  end
24
21
 
25
22
  def test_device_path_stat
@@ -74,5 +71,42 @@ class TestLocal < Test::Unit::TestCase
74
71
  File.open(path_a, "wb") { |fp| fp.write '.' }
75
72
  res = trylocal(env, [ [ a, b ] ])
76
73
  assert_kind_of Regurgitator::LocalFile, res
74
+ assert_equal 200, res.response[0]
75
+ end
76
+
77
+ def test_trylocal_range
78
+ port = 1233
79
+ env = { "REQUEST_METHOD" => "GET", "HTTP_RANGE" => "bytes=5-15" }
80
+ a = URI("http://#@addr:#{port}/dev10/0/004/689/0004689631.fid")
81
+ b = URI("http://#@addr:#{port + 6}/dev11/0/004/689/0004689631.fid")
82
+ assert_nil trylocal(env, [ [ a, b ] ])
83
+
84
+ path_a = "#@tmpdir#{a.path}"
85
+ FileUtils.mkdir_p(File.dirname(path_a))
86
+ Regurgitator::Local.register port, @tmpdir
87
+ File.open(path_a, "wb") { |fp| (0..15).each { |i| fp.write(i.to_s(16)) } }
88
+ res = trylocal(env, [ [ a, b ] ])
89
+ assert_kind_of Regurgitator::LocalFile, res
90
+ assert_equal(206, res.response[0])
91
+ body = ""
92
+ res.response[2].each { |x| body << x }
93
+ expect = (5..15).map { |x| x.to_s(16) }.join("")
94
+ assert_equal expect, body
95
+ end
96
+
97
+ def test_trylocal_bad_range
98
+ port = 1233
99
+ env = { "REQUEST_METHOD" => "GET", "HTTP_RANGE" => "bytes=515-999" }
100
+ a = URI("http://#@addr:#{port}/dev10/0/004/689/0004689631.fid")
101
+ b = URI("http://#@addr:#{port + 6}/dev11/0/004/689/0004689631.fid")
102
+ assert_nil trylocal(env, [ [ a, b ] ])
103
+
104
+ path_a = "#@tmpdir#{a.path}"
105
+ FileUtils.mkdir_p(File.dirname(path_a))
106
+ Regurgitator::Local.register port, @tmpdir
107
+ File.open(path_a, "wb") { |fp| (0..15).each { |i| fp.write(i.to_s(16)) } }
108
+ res = trylocal(env, [ [ a, b ] ])
109
+ assert_kind_of Regurgitator::LocalFile, res
110
+ assert_equal(416, res.response[0])
77
111
  end
78
112
  end
@@ -12,6 +12,7 @@ class TestServerSettings < Test::Unit::TestCase
12
12
  String :field, :size => 50, :null => false, :primary_key => true
13
13
  String :value, :size => 255
14
14
  end
15
+ server_settings_init
15
16
  end
16
17
 
17
18
  def test_zones
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: regurgitator
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
+ - 1
8
9
  - 0
9
- - 0
10
- version: 0.0.0
10
+ version: 0.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Regurgitators
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-10 00:00:00 Z
18
+ date: 2011-11-11 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: rack
@@ -25,11 +25,11 @@ dependencies:
25
25
  requirements:
26
26
  - - ~>
27
27
  - !ruby/object:Gem::Version
28
- hash: 11
28
+ hash: 9
29
29
  segments:
30
30
  - 1
31
- - 2
32
- version: "1.2"
31
+ - 3
32
+ version: "1.3"
33
33
  type: :runtime
34
34
  version_requirements: *id001
35
35
  - !ruby/object:Gem::Dependency
@@ -40,11 +40,11 @@ dependencies:
40
40
  requirements:
41
41
  - - ~>
42
42
  - !ruby/object:Gem::Version
43
- hash: 41
43
+ hash: 61
44
44
  segments:
45
45
  - 3
46
- - 23
47
- version: "3.23"
46
+ - 29
47
+ version: "3.29"
48
48
  type: :runtime
49
49
  version_requirements: *id002
50
50
  - !ruby/object:Gem::Dependency
@@ -55,28 +55,43 @@ dependencies:
55
55
  requirements:
56
56
  - - ~>
57
57
  - !ruby/object:Gem::Version
58
- hash: 9
58
+ hash: 3
59
59
  segments:
60
60
  - 0
61
- - 1
62
- version: "0.1"
61
+ - 4
62
+ version: "0.4"
63
63
  type: :runtime
64
64
  version_requirements: *id003
65
65
  - !ruby/object:Gem::Dependency
66
- name: wrongdoc
66
+ name: rpatricia
67
67
  prerelease: false
68
68
  requirement: &id004 !ruby/object:Gem::Requirement
69
69
  none: false
70
70
  requirements:
71
71
  - - ~>
72
72
  - !ruby/object:Gem::Version
73
- hash: 5
73
+ hash: 27
74
+ segments:
75
+ - 0
76
+ - 8
77
+ version: "0.08"
78
+ type: :runtime
79
+ version_requirements: *id004
80
+ - !ruby/object:Gem::Dependency
81
+ name: wrongdoc
82
+ prerelease: false
83
+ requirement: &id005 !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ~>
87
+ - !ruby/object:Gem::Version
88
+ hash: 3
74
89
  segments:
75
90
  - 1
76
- - 5
77
- version: "1.5"
91
+ - 6
92
+ version: "1.6"
78
93
  type: :development
79
- version_requirements: *id004
94
+ version_requirements: *id005
80
95
  description: |-
81
96
  \Regurgitator is an GPL-licensed library and Rack middleware for
82
97
  serving files stored in MogileFS. It can be embedded inside
@@ -182,7 +197,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
182
197
  requirements: []
183
198
 
184
199
  rubyforge_project: rainbows
185
- rubygems_version: 1.8.1
200
+ rubygems_version: 1.8.5
186
201
  signing_key:
187
202
  specification_version: 3
188
203
  summary: read-only Rack endpoints for MogileFS