Repository: cassandra Updated Branches: refs/heads/cassandra-2.1 729da03c5 -> ace0e6e1d refs/heads/trunk 8955a4658 -> 79e3217f9
Eliminate possibility of CL segment appearing twice in active list patch by Benedict Elliott Smith; reviewed by jbellis for CASSANDRA-6557 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/ace0e6e1 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/ace0e6e1 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/ace0e6e1 Branch: refs/heads/cassandra-2.1 Commit: ace0e6e1d254e109eac52c775033eb79e8387ef5 Parents: 729da03 Author: Jonathan Ellis <[email protected]> Authored: Fri Mar 14 12:40:08 2014 -0500 Committer: Jonathan Ellis <[email protected]> Committed: Fri Mar 14 12:40:08 2014 -0500 ---------------------------------------------------------------------- CHANGES.txt | 2 ++ .../db/commitlog/CommitLogSegmentManager.java | 31 +++++++++----------- 2 files changed, 16 insertions(+), 17 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/ace0e6e1/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 3fdf179..24c8090 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,6 @@ 2.1.0-beta2 + * Eliminate possibility of CL segment appearing twice in active list + (CASSANDRA-6557) * Apply DONTNEED fadvise to commitlog segments (CASSANDRA-6759) * Switch CRC component to Adler and include it for compressed sstables (CASSANDRA-4165) http://git-wip-us.apache.org/repos/asf/cassandra/blob/ace0e6e1/src/java/org/apache/cassandra/db/commitlog/CommitLogSegmentManager.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/commitlog/CommitLogSegmentManager.java b/src/java/org/apache/cassandra/db/commitlog/CommitLogSegmentManager.java index 7a72f79..b0be42c 100644 --- a/src/java/org/apache/cassandra/db/commitlog/CommitLogSegmentManager.java +++ b/src/java/org/apache/cassandra/db/commitlog/CommitLogSegmentManager.java @@ -77,8 +77,6 @@ public class CommitLogSegmentManager private final WaitQueue hasAvailableSegments = new WaitQueue(); - private static final AtomicReferenceFieldUpdater<CommitLogSegmentManager, CommitLogSegment> allocatingFromUpdater = AtomicReferenceFieldUpdater.newUpdater(CommitLogSegmentManager.class, CommitLogSegment.class, "allocatingFrom"); - /** * Tracks commitlog size, in multiples of the segment size. We need to do this so we can "promise" size * adjustments ahead of actually adding/freeing segments on disk, so that the "evict oldest segment" logic @@ -203,33 +201,32 @@ public class CommitLogSegmentManager { while (true) { - Iterator<CommitLogSegment> iter = availableSegments.iterator(); - if (iter.hasNext()) + CommitLogSegment next; + synchronized (this) { - CommitLogSegment next; - if (!allocatingFromUpdater.compareAndSet(this, old, next = iter.next())) - // failed to swap so we should already be able to continue + // do this in a critical section so we can atomically remove from availableSegments and add to allocatingFrom/activeSegments + // see https://issues.apache.org/jira/browse/CASSANDRA-6557?focusedCommentId=13874432&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-13874432 + if (allocatingFrom != old) return; - - iter.remove(); - activeSegments.add(next); - - if (availableSegments.isEmpty()) + next = availableSegments.poll(); + if (next != null) { - // if we've emptied the queue of available segments, trigger the manager to maybe add another - wakeManager(); + allocatingFrom = next; + activeSegments.add(next); } + } + if (next != null) + { if (old != null) { // Now we can run the user defined command just after switching to the new commit log. // (Do this here instead of in the recycle call so we can get a head start on the archive.) CommitLog.instance.archiver.maybeArchive(old.getPath(), old.getName()); - } - // ensure we don't continue to use the old file; not strictly necessary, but cleaner to enforce it - if (old != null) + // ensure we don't continue to use the old file; not strictly necessary, but cleaner to enforce it old.discardUnusedTail(); + } // request that the CL be synced out-of-band, as we've finished a segment CommitLog.instance.requestExtraSync();
