x-newest doesnt return newest metadata for containers
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
OpenStack Object Storage (swift) |
Confirmed
|
Low
|
Unassigned |
Bug Description
Doing a container HEAD with X-Newest header immediately after POST on container sometimes returns stale metadata even though all the container servers are working as normal.
The reason for this behavior is that the operation to update the put-timestamp and metadata in container-stat database isn't atomic.
swift\container
=======
{code}
def PUT(self, req):
...
else: # put container
(1) created = self._update_
metadata = {}
(2) metadata.update(
(key, (value, timestamp))
for key, value in req.headers.
if key.lower() in self.save_headers or
is_sys_
{code}
So, in above code a race condition exists where one thread is trying to update the container metadata while another thread is trying to read the latest metadata. If the read request executes after (1) but before (2) is executed then it gets back stale data with latest timestamp.
Now, the proxy looks at the put-timestamps which will be the same for all replicas and fallbacks to created-at timestamp (x-timestamp). If the replica with stale data was created later than other replicas (when we did container put) then it will have a x-timestamp greater than the others which will make proxy pick the replica with stale data.
swift\proxy\
=======
{code}
if sources:
sources.
source, node = sources.pop()
def source_key(resp):
return float(resp.
{code}
The code in container\server.py should either atomically update the metadata and put-timestamp or update the put-timestamp AFTER it has updated the metadata.
This is serious defect which can lead to inconsistencies in our system which isn't acceptable.
description: | updated |
description: | updated |
summary: |
- x-newest doesnt return newest data under certain race conditions + x-newest doesnt return newest data for containers |
summary: |
- x-newest doesnt return newest data for containers + x-newest doesnt return newest metadata for containers |
summary: |
- x-newest doesnt return newest metadata for containers + x-newest doesnt return newest metadata for containers updated with POST |
summary: |
- x-newest doesnt return newest metadata for containers updated with POST + x-newest doesnt return newest metadata for containers |
I didn't ever really think about using X-newest with containers - that works?
Oh, how interesting, if you do your metadata updates with PUT instead of POST you can get a newer timestamp... hrmm....
Aren't container metadata updates sorta racy anyway? What with read modify write all up in there?
Also you say "[in]consistencies in our system which isn't acceptable" - can you elaborate? AP systems like Swift tend to push clients into gracefully handling stale reads. I'd be fine with minimizing that if the performance implications are reasonable - but what do you expect x-newest to do under failure?