Return-Path: X-Original-To: apmail-cassandra-commits-archive@www.apache.org Delivered-To: apmail-cassandra-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id DB5E07295 for ; Tue, 27 Dec 2011 20:17:52 +0000 (UTC) Received: (qmail 37875 invoked by uid 500); 27 Dec 2011 20:17:52 -0000 Delivered-To: apmail-cassandra-commits-archive@cassandra.apache.org Received: (qmail 37847 invoked by uid 500); 27 Dec 2011 20:17:52 -0000 Mailing-List: contact commits-help@cassandra.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cassandra.apache.org Delivered-To: mailing list commits@cassandra.apache.org Received: (qmail 37839 invoked by uid 99); 27 Dec 2011 20:17:52 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 27 Dec 2011 20:17:52 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 27 Dec 2011 20:17:42 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 75D9C2388A2C for ; Tue, 27 Dec 2011 20:17:19 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: svn commit: r1225001 [1/2] - in /cassandra/trunk: lib/ lib/licenses/ src/java/org/apache/cassandra/db/ test/unit/org/apache/cassandra/db/ Date: Tue, 27 Dec 2011 20:17:18 -0000 To: commits@cassandra.apache.org From: jbellis@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20111227201719.75D9C2388A2C@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: jbellis Date: Tue Dec 27 20:17:17 2011 New Revision: 1225001 URL: http://svn.apache.org/viewvc?rev=1225001&view=rev Log: add row-level isolation via SnapTree patch by slebresne; reviewed by jbellis for CASSANDRA-2893 Added: cassandra/trunk/lib/licenses/snaptree-0.1-SNAPSHOT.txt cassandra/trunk/lib/snaptree-0.1-SNAPSHOT.jar cassandra/trunk/src/java/org/apache/cassandra/db/AbstractThreadUnsafeSortedColumns.java cassandra/trunk/src/java/org/apache/cassandra/db/AtomicSortedColumns.java Removed: cassandra/trunk/src/java/org/apache/cassandra/db/ThreadSafeSortedColumns.java Modified: cassandra/trunk/src/java/org/apache/cassandra/db/AbstractColumnContainer.java cassandra/trunk/src/java/org/apache/cassandra/db/ArrayBackedSortedColumns.java cassandra/trunk/src/java/org/apache/cassandra/db/CollationController.java cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamily.java cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilySerializer.java cassandra/trunk/src/java/org/apache/cassandra/db/ISortedColumns.java cassandra/trunk/src/java/org/apache/cassandra/db/Memtable.java cassandra/trunk/src/java/org/apache/cassandra/db/Row.java cassandra/trunk/src/java/org/apache/cassandra/db/RowMutation.java cassandra/trunk/src/java/org/apache/cassandra/db/SuperColumn.java cassandra/trunk/src/java/org/apache/cassandra/db/TreeMapBackedSortedColumns.java cassandra/trunk/test/unit/org/apache/cassandra/db/ArrayBackedSortedColumnsTest.java cassandra/trunk/test/unit/org/apache/cassandra/db/ColumnFamilyTest.java Added: cassandra/trunk/lib/licenses/snaptree-0.1-SNAPSHOT.txt URL: http://svn.apache.org/viewvc/cassandra/trunk/lib/licenses/snaptree-0.1-SNAPSHOT.txt?rev=1225001&view=auto ============================================================================== --- cassandra/trunk/lib/licenses/snaptree-0.1-SNAPSHOT.txt (added) +++ cassandra/trunk/lib/licenses/snaptree-0.1-SNAPSHOT.txt Tue Dec 27 20:17:17 2011 @@ -0,0 +1,776 @@ + + + + + + + + + doc/LICENSE at master from nbronson/snaptree - GitHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+

+ nbronson / + snaptree +

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +

Latest commit to the master branch

+ +
+

+ update to new IDEA install + +

+
+ commit b198f84b0c + +
+ + nbronson + authored + +
+
+
+ + +
+ + + +
+
+ + +
+
+
+
+ Txt + 100644 + 36 lines (27 sloc) + 1.715 kb +
+ +
+
+ + + + + +
+
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+
+
+
SNAPTREE LICENSE

Copyright (c) 2009 Stanford University, unless otherwise specified.
All rights reserved.

This software was developed by the Pervasive Parallelism Laboratory of
Stanford University, California, USA.

Permission to use, copy, modify, and distribute this software in source
or binary form for any purpose with or without fee is hereby granted,
provided that the following conditions are met:

   1. Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.

   2. Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

   3. Neither the name of Stanford University nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.


THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHE RWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

+
+
+ +
+
+
+
+ +
+ + + +
+
+ + + + + + + + +
+

Markdown Cheat Sheet

+ +
+ +
+
+

Format Text

+

Headers

+
+# This is an <h1> tag
+## This is an <h2> tag
+###### This is an <h6> tag
+

Text styles

+
+*This text will be italic*
+_This will also be italic_
+**This text will be bold**
+__This will also be bold__
+
+*You **can** combine them*
+
+
+
+

Lists

+

Unordered

+
+* Item 1
+* Item 2
+  * Item 2a
+  * Item 2b
+

Ordered

+
+1. Item 1
+2. Item 2
+3. Item 3
+   * Item 3a
+   * Item 3b
+
+
+

Miscellaneous

+

Images

+
+![GitHub Logo](/images/logo.png)
+Format: ![Alt Text](url)
+
+

Links

+
+http://github.com - automatic!
+[GitHub](http://github.com)
+

Blockquotes

+
+As Kanye West said:
+
+> We're living the future so
+> the present is our past.
+
+
+
+
+ +

Code Examples in Markdown

+
+

Syntax highlighting with GFM

+
+```javascript
+function fancyAlert(arg) {
+  if(arg) {
+    $.facebox({div:'#foo'})
+  }
+}
+```
+
+
+

Or, indent your code 4 spaces

+
+Here is a Python code example
+without syntax highlighting:
+
+    def foo:
+      if not bar:
+        return true
+
+
+

Inline code for comments

+
+I think you should use an
+`<addr>` element here instead.
+
+
+ +
+ + + +
+ +
+

Something went wrong with that request. Please try again. Dismiss

+
+ + + + + + + Added: cassandra/trunk/lib/snaptree-0.1-SNAPSHOT.jar URL: http://svn.apache.org/viewvc/cassandra/trunk/lib/snaptree-0.1-SNAPSHOT.jar?rev=1225001&view=auto ============================================================================== Files cassandra/trunk/lib/snaptree-0.1-SNAPSHOT.jar (added) and cassandra/trunk/lib/snaptree-0.1-SNAPSHOT.jar Tue Dec 27 20:17:17 2011 differ Modified: cassandra/trunk/src/java/org/apache/cassandra/db/AbstractColumnContainer.java URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/AbstractColumnContainer.java?rev=1225001&r1=1225000&r2=1225001&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/db/AbstractColumnContainer.java (original) +++ cassandra/trunk/src/java/org/apache/cassandra/db/AbstractColumnContainer.java Tue Dec 27 20:17:17 2011 @@ -18,31 +18,24 @@ package org.apache.cassandra.db; import java.nio.ByteBuffer; -import java.security.MessageDigest; import java.util.Collection; import java.util.Iterator; -import java.util.Map; import java.util.SortedSet; -import java.util.concurrent.ConcurrentSkipListMap; -import java.util.concurrent.atomic.AtomicReference; +import com.google.common.base.Function; +import com.google.common.base.Functions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.apache.cassandra.config.CFMetaData; -import org.apache.cassandra.config.DatabaseDescriptor; -import org.apache.cassandra.db.filter.QueryPath; import org.apache.cassandra.db.marshal.AbstractType; import org.apache.cassandra.io.util.IIterableColumns; import org.apache.cassandra.utils.Allocator; -import org.apache.cassandra.utils.FBUtilities; import org.apache.cassandra.utils.HeapAllocator; public abstract class AbstractColumnContainer implements IColumnContainer, IIterableColumns { private static Logger logger = LoggerFactory.getLogger(AbstractColumnContainer.class); - protected final AtomicReference deletionInfo = new AtomicReference(new DeletionInfo()); protected final ISortedColumns columns; protected AbstractColumnContainer(ISortedColumns columns) @@ -53,20 +46,12 @@ public abstract class AbstractColumnCont @Deprecated // TODO this is a hack to set initial value outside constructor public void delete(int localtime, long timestamp) { - deletionInfo.set(new DeletionInfo(timestamp, localtime)); + columns.delete(new ISortedColumns.DeletionInfo(timestamp, localtime)); } public void delete(AbstractColumnContainer cc2) { - // Keeping deletion info for max markedForDeleteAt value - DeletionInfo current; - DeletionInfo cc2Info = cc2.deletionInfo.get(); - while (true) - { - current = deletionInfo.get(); - if (current.markedForDeleteAt >= cc2Info.markedForDeleteAt || deletionInfo.compareAndSet(current, cc2Info)) - break; - } + columns.delete(cc2.columns.getDeletionInfo()); } public boolean isMarkedForDelete() @@ -76,12 +61,12 @@ public abstract class AbstractColumnCont public long getMarkedForDeleteAt() { - return deletionInfo.get().markedForDeleteAt; + return columns.getDeletionInfo().markedForDeleteAt; } public int getLocalDeletionTime() { - return deletionInfo.get().localDeletionTime; + return columns.getDeletionInfo().localDeletionTime; } public AbstractType getComparator() @@ -96,27 +81,20 @@ public abstract class AbstractColumnCont */ public void maybeResetDeletionTimes(int gcBefore) { - while (true) - { - DeletionInfo current = deletionInfo.get(); - // Stop if either we don't need to change the deletion info (it's - // still MIN_VALUE or not expired yet) or we've succesfully changed it - if (current.localDeletionTime == Integer.MIN_VALUE - || current.localDeletionTime > gcBefore - || deletionInfo.compareAndSet(current, new DeletionInfo())) - { - break; - } - } + columns.maybeResetDeletionTimes(gcBefore); } /** * We need to go through each column in the column container and resolve it before adding */ + public void addAll(AbstractColumnContainer cc, Allocator allocator, Function transformation) + { + columns.addAll(cc.columns, allocator, transformation); + } + public void addAll(AbstractColumnContainer cc, Allocator allocator) { - columns.addAll(cc.columns, allocator); - delete(cc); + addAll(cc, allocator, Functions.identity()); } public void addColumn(IColumn column) @@ -166,39 +144,7 @@ public abstract class AbstractColumnCont public void retainAll(AbstractColumnContainer container) { - Iterator iter = iterator(); - Iterator toRetain = container.iterator(); - IColumn current = iter.hasNext() ? iter.next() : null; - IColumn retain = toRetain.hasNext() ? toRetain.next() : null; - AbstractType comparator = getComparator(); - while (current != null && retain != null) - { - int c = comparator.compare(current.name(), retain.name()); - if (c == 0) - { - if (current instanceof SuperColumn) - { - assert retain instanceof SuperColumn; - ((SuperColumn)current).retainAll((SuperColumn)retain); - } - current = iter.hasNext() ? iter.next() : null; - retain = toRetain.hasNext() ? toRetain.next() : null; - } - else if (c < 0) - { - iter.remove(); - current = iter.hasNext() ? iter.next() : null; - } - else // c > 0 - { - retain = toRetain.hasNext() ? toRetain.next() : null; - } - } - while (current != null) - { - iter.remove(); - current = iter.hasNext() ? iter.next() : null; - } + columns.retainAll(container.columns); } public int getColumnCount() @@ -249,23 +195,6 @@ public abstract class AbstractColumnCont return columns.reverseIterator(start); } - protected static class DeletionInfo - { - public final long markedForDeleteAt; - public final int localDeletionTime; - - public DeletionInfo() - { - this(Long.MIN_VALUE, Integer.MIN_VALUE); - } - - public DeletionInfo(long markedForDeleteAt, int localDeletionTime) - { - this.markedForDeleteAt = markedForDeleteAt; - this.localDeletionTime = localDeletionTime; - } - } - public boolean hasExpiredTombstones(int gcBefore) { if (isMarkedForDelete() && getLocalDeletionTime() < gcBefore) Added: cassandra/trunk/src/java/org/apache/cassandra/db/AbstractThreadUnsafeSortedColumns.java URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/AbstractThreadUnsafeSortedColumns.java?rev=1225001&view=auto ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/db/AbstractThreadUnsafeSortedColumns.java (added) +++ cassandra/trunk/src/java/org/apache/cassandra/db/AbstractThreadUnsafeSortedColumns.java Tue Dec 27 20:17:17 2011 @@ -0,0 +1,111 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cassandra.db; + +import java.util.Iterator; + +import com.google.common.base.Function; + +import org.apache.cassandra.db.marshal.AbstractType; +import org.apache.cassandra.utils.Allocator; + +public abstract class AbstractThreadUnsafeSortedColumns implements ISortedColumns +{ + private DeletionInfo deletionInfo; + + public AbstractThreadUnsafeSortedColumns() + { + deletionInfo = new DeletionInfo(); + } + + public DeletionInfo getDeletionInfo() + { + return deletionInfo; + } + + public void delete(DeletionInfo newInfo) + { + if (deletionInfo.markedForDeleteAt < newInfo.markedForDeleteAt) + // since deletion info is immutable, aliasing it is fine + deletionInfo = newInfo; + } + + public void maybeResetDeletionTimes(int gcBefore) + { + // Update if it's not MIN_VALUE anymore and it has expired + if (deletionInfo.localDeletionTime != Integer.MIN_VALUE && deletionInfo.localDeletionTime <= gcBefore) + deletionInfo = new DeletionInfo(); + } + + public void retainAll(ISortedColumns columns) + { + Iterator iter = iterator(); + Iterator toRetain = columns.iterator(); + IColumn current = iter.hasNext() ? iter.next() : null; + IColumn retain = toRetain.hasNext() ? toRetain.next() : null; + AbstractType comparator = getComparator(); + while (current != null && retain != null) + { + int c = comparator.compare(current.name(), retain.name()); + if (c == 0) + { + if (current instanceof SuperColumn) + { + assert retain instanceof SuperColumn; + ((SuperColumn)current).retainAll((SuperColumn)retain); + } + current = iter.hasNext() ? iter.next() : null; + retain = toRetain.hasNext() ? toRetain.next() : null; + } + else if (c < 0) + { + iter.remove(); + current = iter.hasNext() ? iter.next() : null; + } + else // c > 0 + { + retain = toRetain.hasNext() ? toRetain.next() : null; + } + } + while (current != null) + { + iter.remove(); + current = iter.hasNext() ? iter.next() : null; + } + } + + // Implementations should implement this rather than addAll to avoid + // having to care about the deletion infos + protected abstract void addAllColumns(ISortedColumns columns, Allocator allocator, Function transformation); + + public void addAll(ISortedColumns columns, Allocator allocator, Function transformation) + { + addAllColumns(columns, allocator, transformation); + delete(columns.getDeletionInfo()); + } + + public boolean isEmpty() + { + return size() == 0; + } + + public int getEstimatedColumnCount() + { + return size(); + } +} Modified: cassandra/trunk/src/java/org/apache/cassandra/db/ArrayBackedSortedColumns.java URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/ArrayBackedSortedColumns.java?rev=1225001&r1=1225000&r2=1225001&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/db/ArrayBackedSortedColumns.java (original) +++ cassandra/trunk/src/java/org/apache/cassandra/db/ArrayBackedSortedColumns.java Tue Dec 27 20:17:17 2011 @@ -20,6 +20,8 @@ package org.apache.cassandra.db; import java.nio.ByteBuffer; import java.util.*; +import com.google.common.base.Function; + import org.apache.cassandra.db.marshal.AbstractType; import org.apache.cassandra.utils.Allocator; @@ -30,10 +32,11 @@ import org.apache.cassandra.utils.Alloca * main operations performed are iterating over the map and adding columns * (especially if insertion is in sorted order). */ -public class ArrayBackedSortedColumns extends ArrayList implements ISortedColumns +public class ArrayBackedSortedColumns extends AbstractThreadUnsafeSortedColumns implements ISortedColumns { private final AbstractType comparator; private final boolean reversed; + private final ArrayList columns; public static final ISortedColumns.Factory factory = new Factory() { @@ -58,13 +61,14 @@ public class ArrayBackedSortedColumns ex super(); this.comparator = comparator; this.reversed = reversed; + this.columns = new ArrayList(); } private ArrayBackedSortedColumns(Collection columns, AbstractType comparator, boolean reversed) { - super(columns); this.comparator = comparator; this.reversed = reversed; + this.columns = new ArrayList(columns); } public ISortedColumns.Factory getFactory() @@ -79,7 +83,7 @@ public class ArrayBackedSortedColumns ex public ISortedColumns cloneMe() { - return new ArrayBackedSortedColumns(this, comparator, reversed); + return new ArrayBackedSortedColumns(columns, comparator, reversed); } public boolean isInsertReversed() @@ -98,7 +102,7 @@ public class ArrayBackedSortedColumns ex public IColumn getColumn(ByteBuffer name) { int pos = binarySearch(name); - return pos >= 0 ? get(pos) : null; + return pos >= 0 ? columns.get(pos) : null; } /** @@ -113,14 +117,14 @@ public class ArrayBackedSortedColumns ex */ public void addColumn(IColumn column, Allocator allocator) { - if (isEmpty()) + if (columns.isEmpty()) { - add(column); + columns.add(column); return; } // Fast path if inserting at the tail - int c = compare(get(size() - 1).name(), column.name()); + int c = compare(columns.get(size() - 1).name(), column.name()); // note that we want an assertion here (see addColumn javadoc), but we also want that if // assertion are disabled, addColumn works correctly with unsorted input assert c <= 0 : "Added column does not sort as the " + (reversed ? "first" : "last") + " column"; @@ -128,7 +132,7 @@ public class ArrayBackedSortedColumns ex if (c < 0) { // Insert as last - add(column); + columns.add(column); } else if (c == 0) { @@ -141,7 +145,7 @@ public class ArrayBackedSortedColumns ex if (pos >= 0) resolveAgainst(pos, column, allocator); else - add(-pos-1, column); + columns.add(-pos-1, column); } } @@ -151,7 +155,7 @@ public class ArrayBackedSortedColumns ex */ private void resolveAgainst(int i, IColumn column, Allocator allocator) { - IColumn oldColumn = get(i); + IColumn oldColumn = columns.get(i); if (oldColumn instanceof SuperColumn) { // Delegated to SuperColumn @@ -162,7 +166,7 @@ public class ArrayBackedSortedColumns ex { // calculate reconciled col from old (existing) col and new col IColumn reconciledColumn = column.reconcile(oldColumn, allocator); - set(i, reconciledColumn); + columns.set(i, reconciledColumn); } } @@ -181,7 +185,7 @@ public class ArrayBackedSortedColumns ex while (low <= high) { mid = (low + high) >> 1; - if ((result = compare(name, get(mid).name())) > 0) + if ((result = compare(name, columns.get(mid).name())) > 0) { low = mid + 1; } @@ -197,46 +201,46 @@ public class ArrayBackedSortedColumns ex return -mid - (result < 0 ? 1 : 2); } - public void addAll(ISortedColumns cm, Allocator allocator) + protected void addAllColumns(ISortedColumns cm, Allocator allocator, Function transformation) { if (cm.isEmpty()) return; - IColumn[] copy = toArray(new IColumn[size()]); + IColumn[] copy = columns.toArray(new IColumn[size()]); int idx = 0; Iterator other = reversed ? cm.reverseIterator() : cm.iterator(); IColumn otherColumn = other.next(); - clear(); + columns.clear(); while (idx < copy.length && otherColumn != null) { int c = compare(copy[idx].name(), otherColumn.name()); if (c < 0) { - add(copy[idx]); + columns.add(copy[idx]); idx++; } else if (c > 0) { - add(otherColumn); + columns.add(transformation.apply(otherColumn)); otherColumn = other.hasNext() ? other.next() : null; } else // c == 0 { - add(copy[idx]); - resolveAgainst(size() - 1, otherColumn, allocator); + columns.add(copy[idx]); + resolveAgainst(size() - 1, transformation.apply(otherColumn), allocator); idx++; otherColumn = other.hasNext() ? other.next() : null; } } while (idx < copy.length) { - add(copy[idx++]); + columns.add(copy[idx++]); } while (otherColumn != null) { - add(otherColumn); + columns.add(transformation.apply(otherColumn)); otherColumn = other.hasNext() ? other.next() : null; } } @@ -249,7 +253,7 @@ public class ArrayBackedSortedColumns ex int pos = binarySearch(oldColumn.name()); if (pos >= 0) { - set(pos, newColumn); + columns.set(pos, newColumn); } return pos >= 0; @@ -257,7 +261,7 @@ public class ArrayBackedSortedColumns ex public Collection getSortedColumns() { - return reversed ? new ReverseSortedCollection() : this; + return reversed ? new ReverseSortedCollection() : columns; } public Collection getReverseSortedColumns() @@ -272,29 +276,34 @@ public class ArrayBackedSortedColumns ex { int pos = binarySearch(name); if (pos >= 0) - remove(pos); + columns.remove(pos); } - public SortedSet getColumnNames() + public int size() { - // we could memoize the created set but it's unlikely we'll call this method a lot on the same object anyway - return new ColumnNamesSet(); + return columns.size(); + } + + public void clear() + { + columns.clear(); } - public int getEstimatedColumnCount() + public SortedSet getColumnNames() { - return size(); + // we could memoize the created set but it's unlikely we'll call this method a lot on the same object anyway + return new ColumnNamesSet(); } @Override public Iterator iterator() { - return reversed ? reverseInternalIterator(size()) : super.iterator(); + return reversed ? reverseInternalIterator(size()) : columns.iterator(); } public Iterator reverseIterator() { - return reversed ? super.iterator() : reverseInternalIterator(size()); + return reversed ? columns.iterator() : reverseInternalIterator(size()); } public Iterator iterator(ByteBuffer start) @@ -305,7 +314,7 @@ public class ArrayBackedSortedColumns ex else if (reversed) // listIterator.previous() doesn't return the current element at first but the previous one idx++; - return reversed ? reverseInternalIterator(idx) : listIterator(idx); + return reversed ? reverseInternalIterator(idx) : columns.listIterator(idx); } public Iterator reverseIterator(ByteBuffer start) @@ -316,12 +325,12 @@ public class ArrayBackedSortedColumns ex else if (!reversed) // listIterator.previous() doesn't return the current element at first but the previous one idx++; - return reversed ? listIterator(idx) : reverseInternalIterator(idx); + return reversed ? columns.listIterator(idx) : reverseInternalIterator(idx); } private Iterator reverseInternalIterator(int idx) { - final ListIterator iter = listIterator(idx); + final ListIterator iter = columns.listIterator(idx); return new Iterator() { public boolean hasNext() @@ -345,7 +354,7 @@ public class ArrayBackedSortedColumns ex { public int size() { - return ArrayBackedSortedColumns.this.size(); + return columns.size(); } public Iterator iterator() @@ -361,12 +370,12 @@ public class ArrayBackedSortedColumns ex public IColumn next() { - return ArrayBackedSortedColumns.this.get(idx--); + return columns.get(idx--); } public void remove() { - ArrayBackedSortedColumns.this.remove(idx--); + columns.remove(idx--); } }; } @@ -376,12 +385,12 @@ public class ArrayBackedSortedColumns ex { public int size() { - return ArrayBackedSortedColumns.this.size(); + return columns.size(); } public Iterator iterator() { - return ArrayBackedSortedColumns.super.iterator(); + return columns.iterator(); } } @@ -389,7 +398,7 @@ public class ArrayBackedSortedColumns ex { public int size() { - return ArrayBackedSortedColumns.this.size(); + return columns.size(); } public Iterator iterator() @@ -416,7 +425,7 @@ public class ArrayBackedSortedColumns ex public Comparator comparator() { - return ArrayBackedSortedColumns.this.getComparator(); + return getComparator(); } public ByteBuffer first() @@ -424,7 +433,7 @@ public class ArrayBackedSortedColumns ex final ArrayBackedSortedColumns outerList = ArrayBackedSortedColumns.this; if (outerList.isEmpty()) throw new NoSuchElementException(); - return outerList.get(outerList.reversed ? size() - 1 : 0).name(); + return outerList.columns.get(outerList.reversed ? size() - 1 : 0).name(); } public ByteBuffer last() @@ -432,7 +441,7 @@ public class ArrayBackedSortedColumns ex final ArrayBackedSortedColumns outerList = ArrayBackedSortedColumns.this; if (outerList.isEmpty()) throw new NoSuchElementException(); - return outerList.get(outerList.reversed ? 0 : size() - 1).name(); + return outerList.columns.get(outerList.reversed ? 0 : size() - 1).name(); } /* Added: cassandra/trunk/src/java/org/apache/cassandra/db/AtomicSortedColumns.java URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/AtomicSortedColumns.java?rev=1225001&view=auto ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/db/AtomicSortedColumns.java (added) +++ cassandra/trunk/src/java/org/apache/cassandra/db/AtomicSortedColumns.java Tue Dec 27 20:17:17 2011 @@ -0,0 +1,394 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cassandra.db; + +import java.nio.ByteBuffer; +import java.util.*; +import java.util.concurrent.atomic.AtomicReference; + +import com.google.common.base.Function; +import edu.stanford.ppl.concurrent.SnapTreeMap; + +import org.apache.cassandra.db.marshal.AbstractType; +import org.apache.cassandra.utils.Allocator; + + +/** + * A thread-safe and atomic ISortedColumns implementation. + * Operations (in particular addAll) on this implemenation are atomic and + * isolated (in the sense of ACID). Typically a addAll is guaranteed that no + * other thread can see the state where only parts but not all columns have + * been added. + * + * The implementation uses snaptree (https://github.com/nbronson/snaptree), + * and in particular it's copy-on-write clone operation to achieve its + * atomicity guarantee. + * + * WARNING: removing element through getSortedColumns().iterator() is *not* + * isolated of other operations and could actually be fully ignored in the + * face of a concurrent. Don't use it unless in a non-concurrent context. + * + * TODO: check the snaptree license make it ok to use + */ +public class AtomicSortedColumns implements ISortedColumns +{ + private final AtomicReference ref; + + public static final ISortedColumns.Factory factory = new Factory() + { + public ISortedColumns create(AbstractType comparator, boolean insertReversed) + { + return new AtomicSortedColumns(comparator); + } + + public ISortedColumns fromSorted(SortedMap sortedMap, boolean insertReversed) + { + return new AtomicSortedColumns(sortedMap); + } + }; + + public static ISortedColumns.Factory factory() + { + return factory; + } + + private AtomicSortedColumns(AbstractType comparator) + { + this(new Holder(comparator)); + } + + private AtomicSortedColumns(SortedMap columns) + { + this(new Holder(columns)); + } + + private AtomicSortedColumns(Holder holder) + { + this.ref = new AtomicReference(holder); + } + + public AbstractType getComparator() + { + return (AbstractType)ref.get().map.comparator(); + } + + public ISortedColumns.Factory getFactory() + { + return factory; + } + + public ISortedColumns cloneMe() + { + return new AtomicSortedColumns(ref.get().cloneMe()); + } + + public DeletionInfo getDeletionInfo() + { + return ref.get().deletionInfo; + } + + public void delete(DeletionInfo info) + { + // Keeping deletion info for max markedForDeleteAt value + Holder current; + do + { + current = ref.get(); + if (current.deletionInfo.markedForDeleteAt >= info.markedForDeleteAt) + break; + } + while (!ref.compareAndSet(current, current.with(info))); + } + + public void maybeResetDeletionTimes(int gcBefore) + { + Holder current; + do + { + current = ref.get(); + // Stop if we don't need to change the deletion info (it's still MIN_VALUE or not expired yet) + if (current.deletionInfo.localDeletionTime == Integer.MIN_VALUE || current.deletionInfo.localDeletionTime > gcBefore) + break; + } + while (!ref.compareAndSet(current, current.with(new DeletionInfo()))); + } + + public void retainAll(ISortedColumns columns) + { + Holder current, modified; + do + { + current = ref.get(); + modified = current.cloneMe(); + modified.retainAll(columns); + } + while (!ref.compareAndSet(current, modified)); + } + + public void addColumn(IColumn column, Allocator allocator) + { + Holder current, modified; + do + { + current = ref.get(); + modified = current.cloneMe(); + modified.addColumn(column, allocator); + } + while (!ref.compareAndSet(current, modified)); + } + + public void addAll(ISortedColumns cm, Allocator allocator, Function transformation) + { + /* + * This operation needs to atomicity and isolation. To that end, we + * add the new column to a copy of the map (a cheap O(1) snapTree + * clone) and atomically compare and swap when everything has been + * added. Of course, we must not forget to update the deletion times + * too. + * In case we are adding a lot of columns, failing the final compare + * and swap could be expensive. To mitigate, we check we haven't been + * beaten by another thread after every column addition. If we have, + * we bail early, avoiding unnecessary work if possible. + */ + Holder current, modified; + main_loop: + do + { + current = ref.get(); + DeletionInfo newDelInfo = current.deletionInfo; + if (newDelInfo.markedForDeleteAt < cm.getDeletionInfo().markedForDeleteAt) + newDelInfo = cm.getDeletionInfo(); + modified = new Holder(current.map.clone(), newDelInfo); + + for (IColumn column : cm.getSortedColumns()) + { + modified.addColumn(transformation.apply(column), allocator); + // bail early if we know we've been beaten + if (ref.get() != current) + continue main_loop; + } + } + while (!ref.compareAndSet(current, modified)); + } + + public boolean replace(IColumn oldColumn, IColumn newColumn) + { + if (!oldColumn.name().equals(newColumn.name())) + throw new IllegalArgumentException(); + + Holder current, modified; + boolean replaced; + do + { + current = ref.get(); + modified = current.cloneMe(); + replaced = modified.map.replace(oldColumn.name(), oldColumn, newColumn); + } + while (!ref.compareAndSet(current, modified)); + return replaced; + } + + public void removeColumn(ByteBuffer name) + { + Holder current, modified; + do + { + current = ref.get(); + modified = current.cloneMe(); + modified.map.remove(name); + } + while (!ref.compareAndSet(current, modified)); + } + + public void clear() + { + Holder current, modified; + do + { + current = ref.get(); + modified = current.clear(); + } + while (!ref.compareAndSet(current, modified)); + } + + public IColumn getColumn(ByteBuffer name) + { + return ref.get().map.get(name); + } + + public SortedSet getColumnNames() + { + return ref.get().map.keySet(); + } + + public Collection getSortedColumns() + { + return ref.get().map.values(); + } + + public Collection getReverseSortedColumns() + { + return ref.get().map.descendingMap().values(); + } + + public int size() + { + return ref.get().map.size(); + } + + public int getEstimatedColumnCount() + { + return size(); + } + + public boolean isEmpty() + { + return ref.get().map.isEmpty(); + } + + public Iterator iterator() + { + return getSortedColumns().iterator(); + } + + public Iterator reverseIterator() + { + return getReverseSortedColumns().iterator(); + } + + public Iterator iterator(ByteBuffer start) + { + return ref.get().map.tailMap(start).values().iterator(); + } + + public Iterator reverseIterator(ByteBuffer start) + { + return ref.get().map.descendingMap().tailMap(start).values().iterator(); + } + + public boolean isInsertReversed() + { + return false; + } + + private static class Holder + { + final SnapTreeMap map; + final DeletionInfo deletionInfo; + + Holder(AbstractType comparator) + { + this(new SnapTreeMap(comparator), new DeletionInfo()); + } + + Holder(SortedMap columns) + { + this(new SnapTreeMap(columns), new DeletionInfo()); + } + + Holder(SnapTreeMap map, DeletionInfo deletionInfo) + { + this.map = map; + this.deletionInfo = deletionInfo; + } + + Holder cloneMe() + { + return with(map.clone()); + } + + Holder with(DeletionInfo info) + { + return new Holder(map, info); + } + + Holder with(SnapTreeMap newMap) + { + return new Holder(newMap, deletionInfo); + } + + // There is no point in cloning the underlying map to clear it + // afterwards. + Holder clear() + { + return new Holder(new SnapTreeMap(map.comparator()), deletionInfo); + } + + void addColumn(IColumn column, Allocator allocator) + { + ByteBuffer name = column.name(); + IColumn oldColumn; + while ((oldColumn = map.putIfAbsent(name, column)) != null) + { + if (oldColumn instanceof SuperColumn) + { + assert column instanceof SuperColumn; + ((SuperColumn) oldColumn).putColumn((SuperColumn)column, allocator); + break; // Delegated to SuperColumn + } + else + { + // calculate reconciled col from old (existing) col and new col + IColumn reconciledColumn = column.reconcile(oldColumn, allocator); + if (map.replace(name, oldColumn, reconciledColumn)) + break; + + // We failed to replace column due to a concurrent update or a concurrent removal. Keep trying. + // (Currently, concurrent removal should not happen (only updates), but let us support that anyway.) + } + } + } + + void retainAll(ISortedColumns columns) + { + Iterator iter = map.values().iterator(); + Iterator toRetain = columns.iterator(); + IColumn current = iter.hasNext() ? iter.next() : null; + IColumn retain = toRetain.hasNext() ? toRetain.next() : null; + Comparator comparator = map.comparator(); + while (current != null && retain != null) + { + int c = comparator.compare(current.name(), retain.name()); + if (c == 0) + { + if (current instanceof SuperColumn) + { + assert retain instanceof SuperColumn; + ((SuperColumn)current).retainAll((SuperColumn)retain); + } + current = iter.hasNext() ? iter.next() : null; + retain = toRetain.hasNext() ? toRetain.next() : null; + } + else if (c < 0) + { + iter.remove(); + current = iter.hasNext() ? iter.next() : null; + } + else // c > 0 + { + retain = toRetain.hasNext() ? toRetain.next() : null; + } + } + while (current != null) + { + iter.remove(); + current = iter.hasNext() ? iter.next() : null; + } + } + } +} Modified: cassandra/trunk/src/java/org/apache/cassandra/db/CollationController.java URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/CollationController.java?rev=1225001&r1=1225000&r2=1225001&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/db/CollationController.java (original) +++ cassandra/trunk/src/java/org/apache/cassandra/db/CollationController.java Tue Dec 27 20:17:17 2011 @@ -76,7 +76,7 @@ public class CollationController logger.debug("collectTimeOrderedData"); ISortedColumns.Factory factory = mutableColumns - ? ThreadSafeSortedColumns.factory() + ? AtomicSortedColumns.factory() : TreeMapBackedSortedColumns.factory(); ColumnFamily container = ColumnFamily.create(cfs.metadata, factory, filter.filter.isReversed()); List iterators = new ArrayList(); @@ -209,7 +209,7 @@ public class CollationController { logger.debug("collectAllData"); ISortedColumns.Factory factory = mutableColumns - ? ThreadSafeSortedColumns.factory() + ? AtomicSortedColumns.factory() : ArrayBackedSortedColumns.factory(); List iterators = new ArrayList(); ColumnFamily returnCF = ColumnFamily.create(cfs.metadata, factory, filter.filter.isReversed()); Modified: cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamily.java URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamily.java?rev=1225001&r1=1225000&r2=1225001&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamily.java (original) +++ cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamily.java Tue Dec 27 20:17:17 2011 @@ -61,7 +61,7 @@ public class ColumnFamily extends Abstra public static ColumnFamily create(CFMetaData cfm) { - return create(cfm, ThreadSafeSortedColumns.factory()); + return create(cfm, TreeMapBackedSortedColumns.factory()); } public static ColumnFamily create(CFMetaData cfm, ISortedColumns.Factory factory) @@ -84,8 +84,7 @@ public class ColumnFamily extends Abstra public ColumnFamily cloneMeShallow(ISortedColumns.Factory factory, boolean reversedInsertOrder) { ColumnFamily cf = ColumnFamily.create(cfm, factory, reversedInsertOrder); - // since deletion info is immutable, aliasing it is fine - cf.deletionInfo.set(deletionInfo.get()); + cf.delete(this); return cf; } @@ -108,8 +107,7 @@ public class ColumnFamily extends Abstra public ColumnFamily cloneMe() { ColumnFamily cf = new ColumnFamily(cfm, columns.cloneMe()); - // since deletion info is immutable, aliasing it is fine - cf.deletionInfo.set(deletionInfo.get()); + cf.delete(this); return cf; } Modified: cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilySerializer.java URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilySerializer.java?rev=1225001&r1=1225000&r2=1225001&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilySerializer.java (original) +++ cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilySerializer.java Tue Dec 27 20:17:17 2011 @@ -115,7 +115,7 @@ public class ColumnFamilySerializer impl public ColumnFamily deserialize(DataInput dis) throws IOException { - return deserialize(dis, IColumnSerializer.Flag.LOCAL, ThreadSafeSortedColumns.factory()); + return deserialize(dis, IColumnSerializer.Flag.LOCAL, TreeMapBackedSortedColumns.factory()); } public ColumnFamily deserialize(DataInput dis, IColumnSerializer.Flag flag, ISortedColumns.Factory factory) throws IOException Modified: cassandra/trunk/src/java/org/apache/cassandra/db/ISortedColumns.java URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/ISortedColumns.java?rev=1225001&r1=1225000&r2=1225001&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/db/ISortedColumns.java (original) +++ cassandra/trunk/src/java/org/apache/cassandra/db/ISortedColumns.java Tue Dec 27 20:17:17 2011 @@ -23,6 +23,8 @@ import java.util.Iterator; import java.util.SortedMap; import java.util.SortedSet; +import com.google.common.base.Function; + import org.apache.cassandra.db.marshal.AbstractType; import org.apache.cassandra.io.util.IIterableColumns; import org.apache.cassandra.utils.Allocator; @@ -46,6 +48,11 @@ public interface ISortedColumns extends */ public Factory getFactory(); + public DeletionInfo getDeletionInfo(); + public void delete(DeletionInfo info); + public void maybeResetDeletionTimes(int gcBefore); + public void retainAll(ISortedColumns columns); + /** * Adds a column to this column map. * If a column with the same name is already present in the map, it will @@ -62,7 +69,7 @@ public interface ISortedColumns extends * * but is potentially faster. */ - public void addAll(ISortedColumns cm, Allocator allocator); + public void addAll(ISortedColumns cm, Allocator allocator, Function transformation); /** * Replace oldColumn if present by newColumn. @@ -161,4 +168,22 @@ public interface ISortedColumns extends */ public ISortedColumns fromSorted(SortedMap sm, boolean insertReversed); } + + public static class DeletionInfo + { + public final long markedForDeleteAt; + public final int localDeletionTime; + + public DeletionInfo() + { + this(Long.MIN_VALUE, Integer.MIN_VALUE); + } + + public DeletionInfo(long markedForDeleteAt, int localDeletionTime) + { + this.markedForDeleteAt = markedForDeleteAt; + this.localDeletionTime = localDeletionTime; + } + } + } Modified: cassandra/trunk/src/java/org/apache/cassandra/db/Memtable.java URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/Memtable.java?rev=1225001&r1=1225000&r2=1225001&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/db/Memtable.java (original) +++ cassandra/trunk/src/java/org/apache/cassandra/db/Memtable.java Tue Dec 27 20:17:17 2011 @@ -25,6 +25,7 @@ import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicLong; +import com.google.common.base.Function; import com.google.common.collect.Iterators; import com.google.common.collect.PeekingIterator; import org.slf4j.Logger; @@ -82,7 +83,15 @@ public class Memtable public final ColumnFamilyStore cfs; private final long creationTime; - private SlabAllocator allocator = new SlabAllocator(); + private final SlabAllocator allocator = new SlabAllocator(); + // We really only need one column by allocator but one by memtable is not a big waste and avoids needing allocators to know about CFS + private final Function localCopyFunction = new Function() + { + public IColumn apply(IColumn c) + { + return c.localCopy(cfs, allocator); + }; + }; public Memtable(ColumnFamilyStore cfs) { @@ -203,25 +212,19 @@ public class Memtable ? cf.isMarkedForDelete() ? 1 : 0 : cf.getColumnCount()); - ColumnFamily clonedCf = columnFamilies.get(key); - // if the row doesn't exist yet in the memtable, clone cf to our allocator. - if (clonedCf == null) - { - clonedCf = cf.cloneMeShallow(); - for (IColumn column : cf.getSortedColumns()) - clonedCf.addColumn(column.localCopy(cfs, allocator)); - clonedCf = columnFamilies.putIfAbsent(new DecoratedKey(key.token, allocator.clone(key.key)), clonedCf); - if (clonedCf == null) - return; - // else there was a race and the other thread won. fall through to updating his CF object + + ColumnFamily previous = columnFamilies.get(key); + + if (previous == null) + { + ColumnFamily empty = cf.cloneMeShallow(AtomicSortedColumns.factory(), false); + // We'll add the columns later. This avoids wasting works if we get beaten in the putIfAbsent + previous = columnFamilies.putIfAbsent(new DecoratedKey(key.token, allocator.clone(key.key)), empty); + if (previous == null) + previous = empty; } - // we duplicate the funcationality of CF.resolve here to avoid having to either pass the Memtable in for - // the cloning operation, or cloning the CF container as well as the Columns. fortunately, resolve - // is really quite simple: - clonedCf.delete(cf); - for (IColumn column : cf.getSortedColumns()) - clonedCf.addColumn(column.localCopy(cfs, allocator), allocator); + previous.addAll(cf, allocator, localCopyFunction); } // for debugging Modified: cassandra/trunk/src/java/org/apache/cassandra/db/Row.java URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/Row.java?rev=1225001&r1=1225000&r2=1225001&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/db/Row.java (original) +++ cassandra/trunk/src/java/org/apache/cassandra/db/Row.java Tue Dec 27 20:17:17 2011 @@ -70,7 +70,7 @@ public class Row public Row deserialize(DataInput dis, int version) throws IOException { - return deserialize(dis, version, IColumnSerializer.Flag.LOCAL, ThreadSafeSortedColumns.factory()); + return deserialize(dis, version, IColumnSerializer.Flag.LOCAL, TreeMapBackedSortedColumns.factory()); } public long serializedSize(Row row, int version) Modified: cassandra/trunk/src/java/org/apache/cassandra/db/RowMutation.java URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/RowMutation.java?rev=1225001&r1=1225000&r2=1225001&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/db/RowMutation.java (original) +++ cassandra/trunk/src/java/org/apache/cassandra/db/RowMutation.java Tue Dec 27 20:17:17 2011 @@ -398,7 +398,7 @@ public class RowMutation implements IMut for (int i = 0; i < size; ++i) { Integer cfid = Integer.valueOf(dis.readInt()); - ColumnFamily cf = ColumnFamily.serializer().deserialize(dis, flag, ThreadSafeSortedColumns.factory()); + ColumnFamily cf = ColumnFamily.serializer().deserialize(dis, flag, TreeMapBackedSortedColumns.factory()); modifications.put(cfid, cf); } return new RowMutation(table, key, modifications); Modified: cassandra/trunk/src/java/org/apache/cassandra/db/SuperColumn.java URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/SuperColumn.java?rev=1225001&r1=1225000&r2=1225001&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/db/SuperColumn.java (original) +++ cassandra/trunk/src/java/org/apache/cassandra/db/SuperColumn.java Tue Dec 27 20:17:17 2011 @@ -55,7 +55,7 @@ public class SuperColumn extends Abstrac public SuperColumn(ByteBuffer name, AbstractType comparator) { - this(name, ThreadSafeSortedColumns.factory().create(comparator, false)); + this(name, AtomicSortedColumns.factory().create(comparator, false)); } SuperColumn(ByteBuffer name, ISortedColumns columns) @@ -69,16 +69,14 @@ public class SuperColumn extends Abstrac public SuperColumn cloneMeShallow() { SuperColumn sc = new SuperColumn(name, getComparator()); - // since deletion info is immutable, aliasing it is fine - sc.deletionInfo.set(deletionInfo.get()); + sc.delete(this); return sc; } public IColumn cloneMe() { SuperColumn sc = new SuperColumn(name, columns.cloneMe()); - // since deletion info is immutable, aliasing it is fine - sc.deletionInfo.set(deletionInfo.get()); + sc.delete(this); return sc; } @@ -262,8 +260,7 @@ public class SuperColumn extends Abstrac // we don't try to intern supercolumn names, because if we're using Cassandra correctly it's almost // certainly just going to pollute our interning map with unique, dynamic values SuperColumn sc = new SuperColumn(allocator.clone(name), this.getComparator()); - // since deletion info is immutable, aliasing it is fine - sc.deletionInfo.set(deletionInfo.get()); + sc.delete(this); for(IColumn c : columns) { @@ -358,7 +355,7 @@ class SuperColumnSerializer implements I int size = dis.readInt(); ColumnSerializer serializer = Column.serializer(); ColumnSortedMap preSortedMap = new ColumnSortedMap(comparator, serializer, dis, size, flag, expireBefore); - SuperColumn superColumn = new SuperColumn(name, ThreadSafeSortedColumns.factory().fromSorted(preSortedMap, false)); + SuperColumn superColumn = new SuperColumn(name, AtomicSortedColumns.factory().fromSorted(preSortedMap, false)); superColumn.delete(localDeleteTime, markedForDeleteAt); return superColumn; }