Comment 0 for bug 1384451

Revision history for this message
Aditya Sawhney (aditya-sawhney) wrote : x-newest doesnt return newest data under certain race conditions

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\server.py Line 275
=====================================

{code}

def PUT(self, req):
 ...
 else: # put container
(1) created = self._update_or_create(req, broker, timestamp)
  metadata = {}
(2) metadata.update(
   (key, (value, timestamp))
   for key, value in req.headers.iteritems()
   if key.lower() in self.save_headers or
   is_sys_or_user_meta('container', key))
{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. Now, 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\controllers\base.py Line 857
==========================================

{code}
if sources:
 sources.sort(key=lambda s: source_key(s[0]))
 source, node = sources.pop()

def source_key(resp):
    return float(resp.getheader('x-put-timestamp') or
                 resp.getheader('x-timestamp') or 0)
{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 consistencies in our system which isn't acceptable.