You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cassandra.apache.org by Ohad Shacham <oh...@gmail.com> on 2010/09/26 11:38:37 UTC
Atomically adding a column to columns_
Hi,
We are building a tool for detecting non atomic usages of concurrent
collections.
We analyzed your code using our tool and found the following behavior:
Function addColumn at class SuperColumn tries to atomically add a column to
the concurrent collection “columns_” using the following code:
IColumn oldColumn = columns_.putIfAbsent(name, column);
if (oldColumn != null)
{
IColumn reconciledColumn = reconciler.reconcile((Column)column,
(Column)oldColumn);
while (!columns_.replace(name, oldColumn, reconciledColumn)) {
oldColumn = columns_.get(name);
reconciledColumn = reconciler.reconcile((Column)column, (Column)oldColumn);
}
}
This code can throw NullPointerException at function reconcile if there is a
columns_.remove(…) operation on the same key, by a different thread, between
the previous executed “columns_.replace(…)” and “columns_.get(…)”
operations.
Could you please let me know whether you consider this as a bug?
Another very similar scenario can occur at function “addColumn” of class
“ColumnFamily” where the program can throw NullPointerException while
checking the while loop condition.
A possible way of modifying the code for atomically adding a column to
“columns_” can be as follows:
for (;;) {
IColumn oldColumn = columns_.get(name);
if (oldColumn == null) {
if (columns_.putIfAbsent(name, column) == null)
return;
} else {
IColumn reconciledColumn = reconciler.reconcile((Column)column,
(Column)oldColumn);
if (columns_.replace(name, oldColumn, reconciledColumn))
return;
}
}
Thanks,
Ohad
Re: Atomically adding a column to columns_
Posted by Peter Schuller <pe...@infidyne.com>.
> It would be good to document this, or, since the
> correct-even-for-remove logic is not much more complicated, switch to
> that.
Submitted:
https://issues.apache.org/jira/browse/CASSANDRA-1559
--
/ Peter Schuller
Re: Atomically adding a column to columns_
Posted by Jonathan Ellis <jb...@gmail.com>.
On Mon, Sep 27, 2010 at 1:54 PM, Peter Schuller
<pe...@infidyne.com> wrote:
> In the case of this bit of code, I believe, and I am not speaking
> authoritatively, the removal only happens in (1) the read path when
> filtering results (on presumably query-local data) and (2) during
> compaction (on presumably compaction-local data).
Right, remove should only be called on local copies rather than the
global memtable.
It would be good to document this, or, since the
correct-even-for-remove logic is not much more complicated, switch to
that.
--
Jonathan Ellis
Project Chair, Apache Cassandra
co-founder of Riptano, the source for professional Cassandra support
http://riptano.com
Re: Atomically adding a column to columns_
Posted by Peter Schuller <pe...@infidyne.com>.
> Function addColumn at class SuperColumn tries to atomically add a column to
> the concurrent collection “columns_” using the following code:
Deletions in Cassandra involve an insertion of a tombstone rather than
actual column deletion.
In the case of this bit of code, I believe, and I am not speaking
authoritatively, the removal only happens in (1) the read path when
filtering results (on presumably query-local data) and (2) during
compaction (on presumably compaction-local data). I did browse through
the various callers which seemed to confirm that this was the case. In
other words, I do not believe the remove() code path should not ever
be taken concurrently with insertions (by design, and not by
accident).
Anyone care to confirm/deny?
--
/ Peter Schuller