Skip to content

Commit 2d9103f

Browse files
author
David Goetz
committed
adding double quarantine support for db replication
1 parent 92dc9fa commit 2d9103f

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

swift/common/db_replicator.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import math
2121
import time
2222
import shutil
23+
import uuid
24+
import errno
2325

2426
from eventlet import GreenPool, sleep, Timeout, TimeoutError
2527
from eventlet.green import subprocess
@@ -49,7 +51,13 @@ def quarantine_db(object_file, server_type):
4951
quarantine_dir = os.path.abspath(os.path.join(object_dir, '..',
5052
'..', '..', '..', 'quarantined', server_type + 's',
5153
os.path.basename(object_dir)))
52-
renamer(object_dir, quarantine_dir)
54+
try:
55+
renamer(object_dir, quarantine_dir)
56+
except OSError, e:
57+
if e.errno not in (errno.EEXIST, errno.ENOTEMPTY):
58+
raise
59+
quarantine_dir = "%s-%s" % (quarantine_dir, uuid.uuid4().hex)
60+
renamer(object_dir, quarantine_dir)
5361

5462

5563
class ReplConnection(BufferedHTTPConnection):

test/unit/common/test_db_replicator.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717
from contextlib import contextmanager
1818
import os
1919
import logging
20+
import errno
2021

2122
from swift.common import db_replicator
23+
from swift.common import utils
2224
from swift.common.utils import normalize_timestamp
2325
from swift.container import server as container_server
2426

@@ -86,6 +88,8 @@ def getmtime(self, file):
8688

8789
class FakeBroker:
8890
db_file = __file__
91+
get_repl_missing_table = False
92+
db_type = 'container'
8993
def __init__(self, *args, **kwargs):
9094
return None
9195
@contextmanager
@@ -104,6 +108,8 @@ def merge_syncs(self, *args, **kwargs):
104108
def merge_items(self, *args):
105109
self.args = args
106110
def get_replication_info(self):
111+
if self.get_repl_missing_table:
112+
raise Exception('no such table')
107113
return {'delete_timestamp': 0, 'put_timestamp': 1, 'count': 0}
108114
def reclaim(self, item_timestamp, sync_timestamp):
109115
pass
@@ -202,6 +208,35 @@ def test_replicate_object(self):
202208
replicator = TestReplicator({})
203209
replicator._replicate_object('0', 'file', 'node_id')
204210

211+
def test_replicate_object_quarantine(self):
212+
replicator = TestReplicator({})
213+
was_db_file = replicator.brokerclass.db_file
214+
try:
215+
216+
def mock_renamer(was, new, cause_colision=False):
217+
if cause_colision and '-' not in new:
218+
raise OSError(errno.EEXIST, "File already exists")
219+
self.assertEquals('/a/b/c/d/e', was)
220+
if '-' in new:
221+
self.assert_(
222+
new.startswith('/a/quarantined/containers/e-'))
223+
else:
224+
self.assertEquals('/a/quarantined/containers/e', new)
225+
226+
def mock_renamer_error(was, new):
227+
return mock_renamer(was, new, cause_colision=True)
228+
was_renamer = db_replicator.renamer
229+
db_replicator.renamer = mock_renamer
230+
db_replicator.lock_parent_directory = lock_parent_directory
231+
replicator.brokerclass.get_repl_missing_table = True
232+
replicator.brokerclass.db_file = '/a/b/c/d/e/hey'
233+
replicator._replicate_object('0', 'file', 'node_id')
234+
# try the double quarantine
235+
db_replicator.renamer = mock_renamer_error
236+
replicator._replicate_object('0', 'file', 'node_id')
237+
finally:
238+
replicator.brokerclass.db_file = was_db_file
239+
db_replicator.renamer = was_renamer
205240

206241
# def test_dispatch(self):
207242
# rpc = db_replicator.ReplicatorRpc('/', '/', FakeBroker, False)

0 commit comments

Comments
 (0)