Merge lp:~gholt/swift/lobjects5 into lp:~hudson-openstack/swift/trunk

Proposed by gholt
Status: Merged
Approved by: Chuck Thier
Approved revision: 152
Merged at revision: 158
Proposed branch: lp:~gholt/swift/lobjects5
Merge into: lp:~hudson-openstack/swift/trunk
Diff against target: 81 lines (+51/-9)
2 files modified
swift/proxy/server.py (+9/-9)
test/unit/proxy/test_server.py (+42/-0)
To merge this branch: bzr merge lp:~gholt/swift/lobjects5
Reviewer Review Type Date Requested Status
Chuck Thier (community) Approve
John Dickinson Approve
Review via email: mp+44794@code.launchpad.net

Commit message

Change copies of x-object-manifest objects to copy the actual contents of the object, not just the manifest marker itself.

Description of the change

Change copies of x-object-manifest objects to copy the actual contents of the object, not just the manifest marker itself. In this way, you can consolidate the segments of a manifest object into a single whole object, assuming it meets the max-object-size limitations of the cluster.

This seems to be controversial. I'll let others chime in on their views. Here's my explanation:

A copy of a manifest could really do any of the following:
    A) just make a new manifest pointing to the same segments
    B) make a new object with the same contents as the source object (ignoring that it's a manifest)
    C) make a new manifest pointing to newly made copies of the segments

My logic for picking B is:
    A) is really easy/cheap to do client-side
    B) is expensive to do client-side and would actually be useful if done server-side
    C) is crazy

To post a comment you must log in.
lp:~gholt/swift/lobjects5 updated
150. By gholt

Made copies of ridiculously segmented objects error.

151. By gholt

Merge from trunk

152. By gholt

Merge from trunk

Revision history for this message
John Dickinson (notmyname) wrote :

seems good to me

review: Approve
Revision history for this message
Chuck Thier (cthier) wrote :

Looks good

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'swift/proxy/server.py'
2--- swift/proxy/server.py 2011-01-04 23:34:43 +0000
3+++ swift/proxy/server.py 2011-01-05 15:19:45 +0000
4@@ -950,15 +950,15 @@
5 self.container_name = orig_container_name
6 new_req = Request.blank(req.path_info,
7 environ=req.environ, headers=req.headers)
8- if 'x-object-manifest' in source_resp.headers:
9- data_source = iter([''])
10- new_req.content_length = 0
11- new_req.headers['X-Object-Manifest'] = \
12- source_resp.headers['x-object-manifest']
13- else:
14- data_source = source_resp.app_iter
15- new_req.content_length = source_resp.content_length
16- new_req.etag = source_resp.etag
17+ data_source = source_resp.app_iter
18+ new_req.content_length = source_resp.content_length
19+ if new_req.content_length is None:
20+ # This indicates a transfer-encoding: chunked source object,
21+ # which currently only happens because there are more than
22+ # CONTAINER_LISTING_LIMIT segments in a segmented object. In
23+ # this case, we're going to refuse to do the server-side copy.
24+ return HTTPRequestEntityTooLarge(request=req)
25+ new_req.etag = source_resp.etag
26 # we no longer need the X-Copy-From header
27 del new_req.headers['X-Copy-From']
28 for k, v in source_resp.headers.items():
29
30=== modified file 'test/unit/proxy/test_server.py'
31--- test/unit/proxy/test_server.py 2011-01-04 23:34:43 +0000
32+++ test/unit/proxy/test_server.py 2011-01-05 15:19:45 +0000
33@@ -1995,6 +1995,48 @@
34 # will be sent in a single chunk.
35 self.assertEquals(body,
36 '19\r\n1234 1234 1234 1234 1234 \r\n0\r\n\r\n')
37+ # Make a copy of the manifested object, which should
38+ # error since the number of segments exceeds
39+ # CONTAINER_LISTING_LIMIT.
40+ sock = connect_tcp(('localhost', prolis.getsockname()[1]))
41+ fd = sock.makefile()
42+ fd.write('PUT /v1/a/segmented/copy HTTP/1.1\r\nHost: '
43+ 'localhost\r\nConnection: close\r\nX-Auth-Token: '
44+ 't\r\nX-Copy-From: segmented/name\r\nContent-Length: '
45+ '0\r\n\r\n')
46+ fd.flush()
47+ headers = readuntil2crlfs(fd)
48+ exp = 'HTTP/1.1 413'
49+ self.assertEquals(headers[:len(exp)], exp)
50+ body = fd.read()
51+ # After adjusting the CONTAINER_LISTING_LIMIT, make a copy of
52+ # the manifested object which should consolidate the segments.
53+ proxy_server.CONTAINER_LISTING_LIMIT = 10000
54+ sock = connect_tcp(('localhost', prolis.getsockname()[1]))
55+ fd = sock.makefile()
56+ fd.write('PUT /v1/a/segmented/copy HTTP/1.1\r\nHost: '
57+ 'localhost\r\nConnection: close\r\nX-Auth-Token: '
58+ 't\r\nX-Copy-From: segmented/name\r\nContent-Length: '
59+ '0\r\n\r\n')
60+ fd.flush()
61+ headers = readuntil2crlfs(fd)
62+ exp = 'HTTP/1.1 201'
63+ self.assertEquals(headers[:len(exp)], exp)
64+ body = fd.read()
65+ # Retrieve and validate the copy.
66+ sock = connect_tcp(('localhost', prolis.getsockname()[1]))
67+ fd = sock.makefile()
68+ fd.write('GET /v1/a/segmented/copy HTTP/1.1\r\nHost: '
69+ 'localhost\r\nConnection: close\r\nX-Auth-Token: '
70+ 't\r\n\r\n')
71+ fd.flush()
72+ headers = readuntil2crlfs(fd)
73+ exp = 'HTTP/1.1 200'
74+ self.assertEquals(headers[:len(exp)], exp)
75+ self.assert_('x-object-manifest:' not in headers.lower())
76+ self.assert_('Content-Length: 25\r' in headers)
77+ body = fd.read()
78+ self.assertEquals(body, '1234 1234 1234 1234 1234 ')
79 finally:
80 prospa.kill()
81 acc1spa.kill()