diff options
author | Clay Gerrard <clay.gerrard@gmail.com> | 2014-03-17 16:00:46 -0700 |
---|---|---|
committer | Clay Gerrard <clay.gerrard@gmail.com> | 2014-03-17 16:13:43 -0700 |
commit | 2e8bc44c9d0586813587a5711f8e857a31393326 (patch) | |
tree | a744b2466080dcc904a8c0e622ab657e011a48b5 /swift | |
parent | 6cdf784e2f0e3b37fb040d24b57c9ed92166e6c7 (diff) | |
download | swift-2e8bc44c9d0586813587a5711f8e857a31393326.tar.gz |
Fix race on container recreate
There was a path on container recreate that would sometimes allow db to get
reinitialized without updating put_timestamp. Replication would of course fix
it up, but that node would think it's database was deleted till then desipite
just ok'ing a request with a newer X-Timestamp than the deleted_timestamp on
disk.
Change-Id: I8b98afb2aac2e433b6ecb5c421ba0d778cef42fa
Closes-Bug: #1292784
Diffstat (limited to 'swift')
-rw-r--r-- | swift/container/server.py | 26 |
1 files changed, 15 insertions, 11 deletions
diff --git a/swift/container/server.py b/swift/container/server.py index 7f6e30ad9..4242465bf 100644 --- a/swift/container/server.py +++ b/swift/container/server.py @@ -227,6 +227,20 @@ class ContainerController(object): return HTTPNoContent(request=req) return HTTPNotFound() + def _update_or_create(self, req, broker, timestamp): + if not os.path.exists(broker.db_file): + try: + broker.initialize(timestamp) + except DatabaseAlreadyExists: + pass + else: + return True # created + created = broker.is_deleted() + broker.update_put_timestamp(timestamp) + if broker.is_deleted(): + raise HTTPConflict(request=req) + return created + @public @timing_stats() def PUT(self, req): @@ -261,17 +275,7 @@ class ContainerController(object): req.headers['x-etag']) return HTTPCreated(request=req) else: # put container - if not os.path.exists(broker.db_file): - try: - broker.initialize(timestamp) - created = True - except DatabaseAlreadyExists: - created = False - else: - created = broker.is_deleted() - broker.update_put_timestamp(timestamp) - if broker.is_deleted(): - return HTTPConflict(request=req) + created = self._update_or_create(req, broker, timestamp) metadata = {} metadata.update( (key, (value, timestamp)) |