]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
obsync: filestore: separate xattr metadata nspace
authorColin Patrick McCabe <cmccabe@alumni.cmu.edu>
Mon, 16 May 2011 23:51:45 +0000 (16:51 -0700)
committerColin Patrick McCabe <cmccabe@alumni.cmu.edu>
Mon, 16 May 2011 23:51:45 +0000 (16:51 -0700)
User-defined s3 metadata lives in a separate namespace from regular S3
metadata like Content-Type, etc.

Signed-off-by: Colin McCabe <colin.mccabe@dreamhost.com>
src/obsync/obsync.py
src/obsync/test-obsync.py

index c5a66e9024ff941902e8221a6fea37d3e47e091a..db29827560d6479568f5f08b4a360723fec3b575 100755 (executable)
@@ -48,7 +48,7 @@ global xuser
 RGW_META_BUCKET_NAME = ".rgw"
 ACL_XATTR = "rados.acl"
 META_XATTR_PREFIX = "rados.meta."
-CONTENT_TYPE_XATTR = "content_type"
+CONTENT_TYPE_XATTR = "rados.content_type"
 
 ###### Exception classes #######
 class InvalidLocalName(Exception):
@@ -57,7 +57,7 @@ class InvalidLocalName(Exception):
 class NonexistentStore(Exception):
     pass
 
-###### Test Extended Attribute Support #######
+###### Extended Attributes #######
 def test_xattr_support(path):
     test_file = path + "/$TEST"
     f = open(test_file, 'w')
@@ -74,6 +74,15 @@ def test_xattr_support(path):
     finally:
         os.unlink(test_file)
 
+def xattr_is_metadata(k):
+    # miscellaneous user-defined metadata
+    if (k[:len(META_XATTR_PREFIX)] == META_XATTR_PREFIX):
+        return True
+    # content-type
+    elif (k == CONTENT_TYPE_XATTR):
+        return True
+    return False
+
 ###### Helper functions #######
 def mkdir_p(path):
     try:
@@ -410,10 +419,8 @@ class Object(object):
             else:
                 raise
         for k,v in xlist:
-            if (k[:len(META_XATTR_PREFIX)] != META_XATTR_PREFIX):
-                continue
-            k_name = k[len(META_XATTR_PREFIX):]
-            meta[k_name] = v
+            if xattr_is_metadata(k):
+                meta[k] = v
         #print "Object.from_file: path="+path+",md5=" + bytes_to_str(md5) +",size=" + str(size)
         return Object(obj_name, md5, size, meta)
 
@@ -720,8 +727,8 @@ class FileStore(Store):
         shutil.copy(s, d)
         src_acl.write_to_xattr(d)
         # Store metadata in extended attributes
-        for k_name,v in obj.meta.items():
-            xattr.set(d, META_XATTR_PREFIX + k_name, v, namespace=xattr.NS_USER)
+        for k,v in obj.meta.items():
+            xattr.set(d, k, v, namespace=xattr.NS_USER)
     def remove(self, obj):
         if (opts.dry_run):
             return
index 5deb21e2288731c921c012279fc9f021d1785cbb..9b09cc72b59d931d8ab52f0bf054686602a4105a 100755 (executable)
@@ -38,7 +38,7 @@ nonce = 0
 
 ###### Constants #######
 ACL_XATTR = "rados.acl"
-META_XATTR_PREFIX = "rados.meta."
+CONTENT_TYPE_XATTR = "rados.content_type"
 
 ###### Helper functions #######
 def get_nonce():
@@ -176,26 +176,24 @@ def xattr_sync_impl(file_name, meta):
     xlist = xattr.get_all(file_name, namespace=xattr.NS_USER)
     to_delete = []
     to_set = {}
-    for k_name,v in meta.items():
-        to_set[k_name] = v
+    for k,v in meta.items():
+        to_set[k] = v
     for k,v in xlist:
-        if (k[:len(META_XATTR_PREFIX)] != META_XATTR_PREFIX):
+        if (k == ACL_XATTR):
             continue
-        k_name = k[len(META_XATTR_PREFIX):]
-        if (not meta.has_key(k_name)):
-            to_delete.append(k_name)
-        elif (meta[k_name] == v):
-            del to_set[k_name]
+        if (not meta.has_key(k)):
+            to_delete.append(k)
+        elif (meta[k] == v):
+            del to_set[k]
     return to_delete, to_set
 
 def xattr_sync(file_name, meta):
     """ Synchronize the xattrs on a file with a hash of our choosing """
     to_delete, to_set = xattr_sync_impl(file_name, meta)
-    for k_name in to_delete:
-        xattr.remove(file_name, META_XATTR_PREFIX + k_name)
-    for k_name,v in to_set.items():
-        xattr.set(file_name, META_XATTR_PREFIX + k_name,
-                    v, namespace=xattr.NS_USER)
+    for k in to_delete:
+        xattr.remove(file_name, k)
+    for k,v in to_set.items():
+        xattr.set(file_name, k, v, namespace=xattr.NS_USER)
 
 def assert_xattr(file_name, meta):
     """ Raise an exception if the xattrs on a file are not what we expect """
@@ -212,10 +210,9 @@ def assert_xattr(file_name, meta):
     print "GOT: {",
     sep = ""
     for k,v in xattr.get_all(file_name, namespace=xattr.NS_USER):
-        if (k[:len(META_XATTR_PREFIX)] != META_XATTR_PREFIX):
+        if (k == ACL_XATTR):
             continue
-        k_name = k[len(META_XATTR_PREFIX):]
-        print "%s%s:%s" % (sep, k_name, v),
+        print "%s%s:%s" % (sep, k, v),
         sep = ", "
     print "}",
     print
@@ -534,17 +531,19 @@ eggfile = "%s/content_type_test/eggy_thing" % tdir
 f = open(hamfile, 'w')
 f.write("SPAM SPAM SPAM")
 f.close()
-xattr_sync(hamfile, { "content_type" : "Ham" })
-assert_xattr(hamfile, { "content_type" : "Ham" })
+xattr_sync(hamfile, { CONTENT_TYPE_XATTR : "Ham" })
+assert_xattr(hamfile, { CONTENT_TYPE_XATTR : "Ham" })
 f = open(eggfile, 'w')
 f.write("eggs")
 f.close()
-xattr_sync(eggfile, { "content_type" : "Eggs" })
+xattr_sync(eggfile, { CONTENT_TYPE_XATTR : "Eggs" })
 obsync_check("%s/content_type_test" % tdir, opts.buckets[0], ["--delete-after"])
 obsync_check(opts.buckets[0], "%s/content_type_test2" % tdir, ["-c"])
 assert_xattr("%s/content_type_test2/hammy_thing" % tdir,
-        { "content_type" : "Ham" })
+        { CONTENT_TYPE_XATTR : "Ham" })
 assert_xattr("%s/content_type_test2/eggy_thing" % tdir,
-        { "content_type" : "Eggs" })
+        { CONTENT_TYPE_XATTR : "Eggs" })
+
+# Check that content-type is preserved
 
 sys.exit(0)