about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2011-11-08 02:45:40 +0000
committerEric Wong <normalperson@yhbt.net>2011-11-08 02:45:40 +0000
commit1a5b3487e5a38a4897a6461b3907cd6bde501e0c (patch)
treeed354bc6398343262ea104b1d2f718dd080e5a37
parentfd5098ba0825d5ee603265a40e8c62b97191b7b6 (diff)
downloadmogilefs-client-1a5b3487e5a38a4897a6461b3907cd6bde501e0c.tar.gz
This was added in MogileFS 2.45
-rw-r--r--lib/mogilefs/backend.rb1
-rw-r--r--lib/mogilefs/mogilefs.rb49
-rw-r--r--test/test_mogilefs_integration.rb40
3 files changed, 85 insertions, 5 deletions
diff --git a/lib/mogilefs/backend.rb b/lib/mogilefs/backend.rb
index 7b52939..5403c13 100644
--- a/lib/mogilefs/backend.rb
+++ b/lib/mogilefs/backend.rb
@@ -86,6 +86,7 @@ class MogileFS::Backend
   add_command :rename
   add_command :list_keys
   add_command :file_info
+  add_command :file_debug
 
   # MogileFS::Backend commands
 
diff --git a/lib/mogilefs/mogilefs.rb b/lib/mogilefs/mogilefs.rb
index ef01f5b..bbf8740 100644
--- a/lib/mogilefs/mogilefs.rb
+++ b/lib/mogilefs/mogilefs.rb
@@ -219,12 +219,13 @@ class MogileFS::MogileFS < MogileFS::Client
     [ keys, res['next_after'] ]
   end
 
-  # Used to return metadata about a file. Returns the domain, class, expected
-  # length, devcount, etc. Optionally device ids (not paths) can be returned as
-  # well if :devices is specified.
+  # Return metadata about a file as a hash.
+  # Returns the domain, class, expected length, devcount, etc.
+  # Optionally device ids (not paths) can be returned as
+  # well if :devices is specified and +true+.
   #
-  # Should be used for informational purposes, and not usually for dynamically
-  # serving files.
+  # This should only be used for informational purposes, and not usually
+  # for dynamically serving files.
   def file_info(key, args = nil)
     opts = { :domain => @domain, :key => key }
     args and devices = args[:devices] and opts[:devices] = devices ? 1 : 0
@@ -233,4 +234,42 @@ class MogileFS::MogileFS < MogileFS::Client
     devids = rv["devids"] and rv["devids"] = devids.split(/,/).map! { |x| x.to_i }
     rv
   end
+
+  # Given an Integer +fid+ or String +key+ and domain, thorougly search
+  # the database for all occurences of a particular fid.
+  #
+  # Use this sparingly, this command hits the master database numerous
+  # times and is very expensive.  This is not for production use, only
+  # troubleshooting and debugging.
+  #
+  # Searches for fid=666:
+  #
+  #   client.file_debug(666)
+  #
+  # Search for key=foo using the default domain for this object:
+  #
+  #   client.file_debug("foo")
+  #
+  # Search for key=foo in domain="bar":
+  #
+  #   client.file_debug(:key => "foo", :domain => "bar")
+  #
+  def file_debug(args)
+    case args
+    when Integer then args = { "fid" => args }
+    when String then args = { "key" => args }
+    end
+    opts = { :domain => args[:domain] || @domain }.merge!(args)
+
+    rv = @backend.file_debug(opts)
+    rv.each do |k,v|
+      case k
+      when /_(?:classid|devcount|dmid|fid|length|
+            nexttry|fromdevid|failcount|flags|devid|type)\z/x
+        rv[k] = v.to_i
+      when /devids\z/
+        rv[k] = v.split(/,/).map! { |x| x.to_i }
+      end
+    end
+  end
 end
diff --git a/test/test_mogilefs_integration.rb b/test/test_mogilefs_integration.rb
index cf8d178..f5915bd 100644
--- a/test/test_mogilefs_integration.rb
+++ b/test/test_mogilefs_integration.rb
@@ -79,4 +79,44 @@ class TestMogileFSIntegration < TestMogIntegration
     devids.each { |devid| assert_kind_of Integer, devid }
     assert_equal res["devcount"], devids.size
   end
+
+  def test_file_debug
+    assert_equal 3, @client.store_content("file_debug", "default", "BUG")
+    a = @client.file_debug("file_debug")
+    b = @client.file_debug(:key => "file_debug")
+    fid = @client.file_info("file_debug")["fid"]
+    c = @client.file_debug(fid)
+    d = @client.file_debug(:fid => fid)
+
+    [ a, b, c, d ].each do |res|
+      assert_equal fid, res["fid_fid"]
+      assert_equal 0, res["fid_classid"]
+      assert_equal "file_debug", res["fid_dkey"]
+      assert_equal 3, res["fid_length"]
+      assert_kind_of Array, res["devids"]
+      assert_kind_of Integer, res["devids"][0]
+      res["devids"].each do |devid|
+        uri = URI.parse(res["devpath_#{devid}"])
+        assert_equal "http", uri.scheme
+      end
+      assert_equal "default", res["fid_class"]
+    end
+    @client.delete("file_debug")
+    rv = @client.file_debug(fid)
+    assert rv.keys.grep(/\Afid_/).empty?, rv.inspect
+  end
+
+  def test_file_debug_in_progress
+    rv = @client.new_file("file_debug_in_progress") do |http_file|
+      http_file << "ZZZZ"
+      dests = http_file.instance_variable_get(:@dests)
+      dests[0][1] =~ %r{/(\d+)\.fid\z}
+      fid = $1.to_i
+      rv = @client.file_debug(fid)
+      devids = dests.map { |x| x[0].to_i }.sort
+      assert_equal devids, rv["tempfile_devids"].sort
+      assert_equal "file_debug_in_progress", rv["tempfile_dkey"]
+    end
+    assert_equal 4, rv
+  end
 end