The repro is a little more involved than the reconstructor case, but yeah, this can definitely happen. First up, I hacked up handoffs_first to be handoffs_only
diff --git a/swift/obj/replicator.py b/swift/obj/replicator.py
index dcab26fe1..a8891124c 100644
--- a/swift/obj/replicator.py
+++ b/swift/obj/replicator.py
@@ -917,7 +918,8 @@ class ObjectReplicator(Daemon): random.shuffle(jobs)
if self.handoffs_first:
# Move the handoff parts to the front of the list
- jobs.sort(key=lambda job: not job['delete'])
+ jobs = [job for job in jobs if job['delete']] self.job_count = len(jobs)
return jobs
Then widened the race:
diff --git a/swift/obj/replicator.py b/swift/obj/replicator.py
index dcab26fe1..a8891124c 100644
--- a/swift/obj/replicator.py
+++ b/swift/obj/replicator.py
@@ -587,6 +587,7 @@ class ObjectReplicator(Daemon): self.logger.timing_since('partition.delete.timing', begin)
The repro is a little more involved than the reconstructor case, but yeah, this can definitely happen. First up, I hacked up handoffs_first to be handoffs_only
diff --git a/swift/ obj/replicator. py b/swift/ obj/replicator. py .a8891124c 100644 obj/replicator. py obj/replicator. py r(Daemon) :
random. shuffle( jobs) first: key=lambda job: not job['delete'])
self. job_count = len(jobs)
index dcab26fe1.
--- a/swift/
+++ b/swift/
@@ -917,7 +918,8 @@ class ObjectReplicato
if self.handoffs_
# Move the handoff parts to the front of the list
- jobs.sort(
+ jobs = [job for job in jobs if job['delete']]
return jobs
Then widened the race:
diff --git a/swift/ obj/replicator. py b/swift/ obj/replicator. py .a8891124c 100644 obj/replicator. py obj/replicator. py r(Daemon) :
self. logger. timing_ since(' partition. delete. timing' , begin)
index dcab26fe1.
--- a/swift/
+++ b/swift/
@@ -587,6 +587,7 @@ class ObjectReplicato
def delete_ partition( self, path):
self. logger. info(_( "Removing partition: %s"), path)
tpool. execute( shutil. rmtree, path)
+ time.sleep(10)
try:
Letting the replicators run for a bit, I'm down to only two data files.