Do collision detection via Redis metadata
This commit is contained in:
parent
4e7c8f68bb
commit
4ca67c7ea9
@ -289,6 +289,58 @@ module RemoteStorage
|
|||||||
end
|
end
|
||||||
|
|
||||||
def has_name_collision?(user, directory, key)
|
def has_name_collision?(user, directory, key)
|
||||||
|
if settings.use_redis_dir_listing
|
||||||
|
has_name_collision_via_redis?(user, directory, key)
|
||||||
|
else
|
||||||
|
has_name_collision_via_swift?(user, directory, key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_name_collision_via_redis?(user, directory, key)
|
||||||
|
lua_script = <<-EOF
|
||||||
|
local user = ARGV[1]
|
||||||
|
local directory = ARGV[2]
|
||||||
|
local key = ARGV[3]
|
||||||
|
|
||||||
|
-- build table with parent directories from remaining arguments
|
||||||
|
local parent_dir_count = #ARGV - 3
|
||||||
|
local parent_directories = {}
|
||||||
|
for i = 4, 4 + parent_dir_count do
|
||||||
|
table.insert(parent_directories, ARGV[i])
|
||||||
|
end
|
||||||
|
|
||||||
|
-- check for existing directory with the same name as the document
|
||||||
|
local redis_key = "rs_meta:"..user..":"
|
||||||
|
if directory == "" then
|
||||||
|
redis_key = redis_key..key.."/"
|
||||||
|
else
|
||||||
|
redis_key = redis_key..directory.."/"..key.."/"
|
||||||
|
end
|
||||||
|
if redis.call("hget", redis_key, "etag") then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
for index, dir in pairs(parent_directories) do
|
||||||
|
if redis.call("hget", "rs_meta:"..user..":"..dir.."/", "etag") then
|
||||||
|
-- the directory already exists, no need to do further checks
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
-- check for existing document with same name as directory
|
||||||
|
if redis.call("hget", "rs_meta:"..user..":"..dir, "etag") then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
EOF
|
||||||
|
|
||||||
|
parent_directories = parent_directories_for(directory)
|
||||||
|
|
||||||
|
redis.eval(lua_script, nil, [user, directory, key, *parent_directories])
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_name_collision_via_swift?(user, directory, key)
|
||||||
# check for existing directory with the same name as the document
|
# check for existing directory with the same name as the document
|
||||||
url = url_for_key(user, directory, key)
|
url = url_for_key(user, directory, key)
|
||||||
do_head_request("#{url}/") do |res|
|
do_head_request("#{url}/") do |res|
|
||||||
|
@ -64,6 +64,46 @@ describe "App" do
|
|||||||
root_items = redis.smembers "rs_meta:phil:/:items"
|
root_items = redis.smembers "rs_meta:phil:/:items"
|
||||||
root_items.must_equal ["food/"]
|
root_items.must_equal ["food/"]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "name collision checks" do
|
||||||
|
it "is successful when there is no name collision" do
|
||||||
|
put_stub = OpenStruct.new(headers: {etag: "bla"})
|
||||||
|
RestClient.stub :put, put_stub do
|
||||||
|
put "/phil/food/aguacate", "si"
|
||||||
|
end
|
||||||
|
|
||||||
|
last_response.status.must_equal 200
|
||||||
|
|
||||||
|
metadata = redis.hgetall "rs_meta:phil:food/aguacate"
|
||||||
|
metadata["size"].must_equal "2"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "conflicts when there is a directory with same name as document" do
|
||||||
|
put_stub = OpenStruct.new(headers: {etag: "bla"})
|
||||||
|
RestClient.stub :put, put_stub do
|
||||||
|
put "/phil/food/aguacate", "si"
|
||||||
|
put "/phil/food", "wontwork"
|
||||||
|
end
|
||||||
|
|
||||||
|
last_response.status.must_equal 409
|
||||||
|
|
||||||
|
metadata = redis.hgetall "rs_meta:phil:food"
|
||||||
|
metadata.must_be_empty
|
||||||
|
end
|
||||||
|
|
||||||
|
it "conflicts when there is a document with same name as directory" do
|
||||||
|
put_stub = OpenStruct.new(headers: {etag: "bla"})
|
||||||
|
RestClient.stub :put, put_stub do
|
||||||
|
put "/phil/food/aguacate", "si"
|
||||||
|
put "/phil/food/aguacate/empanado", "wontwork"
|
||||||
|
end
|
||||||
|
|
||||||
|
last_response.status.must_equal 409
|
||||||
|
|
||||||
|
metadata = redis.hgetall "rs_meta:phil:food/aguacate/empanado"
|
||||||
|
metadata.must_be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user