You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by sn...@apache.org on 2015/05/15 00:17:27 UTC
cassandra git commit: Make Functions.declared thread-safe
Repository: cassandra
Updated Branches:
refs/heads/trunk 4a5c282f7 -> 7f9ed0ddb
Make Functions.declared thread-safe
Patch by Robert Stupp; Reviewed by Tyler Hobbs for CASSANDRA-9366
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/7f9ed0dd
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/7f9ed0dd
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/7f9ed0dd
Branch: refs/heads/trunk
Commit: 7f9ed0ddbaabbcc94311e25b2df60415da15ede7
Parents: 4a5c282
Author: Robert Stupp <sn...@snazy.de>
Authored: Fri May 15 00:16:18 2015 +0200
Committer: Robert Stupp <sn...@snazy.de>
Committed: Fri May 15 00:16:18 2015 +0200
----------------------------------------------------------------------
CHANGES.txt | 1 +
.../cassandra/cql3/functions/Functions.java | 70 ++++++++++++++------
2 files changed, 52 insertions(+), 19 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/7f9ed0dd/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 325a5f3..0efba98 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
2.2
+ * Make Functions.declared thread-safe
* Add client warnings to native protocol v4 (CASSANDRA-8930)
* Allow roles cache to be invalidated (CASSANDRA-8967)
* Upgrade Snappy (CASSANDRA-9063)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/7f9ed0dd/src/java/org/apache/cassandra/cql3/functions/Functions.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/functions/Functions.java b/src/java/org/apache/cassandra/cql3/functions/Functions.java
index bc0b9d9..7ac8039 100644
--- a/src/java/org/apache/cassandra/cql3/functions/Functions.java
+++ b/src/java/org/apache/cassandra/cql3/functions/Functions.java
@@ -19,9 +19,11 @@ package org.apache.cassandra.cql3.functions;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
-
-import com.google.common.collect.ArrayListMultimap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.cassandra.config.Schema;
import org.apache.cassandra.cql3.*;
@@ -39,7 +41,7 @@ public abstract class Functions
private Functions() {}
- private static final ArrayListMultimap<FunctionName, Function> declared = ArrayListMultimap.create();
+ private static final ConcurrentMap<FunctionName, List<Function>> declared = new ConcurrentHashMap<>();
static
{
@@ -85,20 +87,31 @@ public abstract class Functions
private static void declare(Function fun)
{
- declared.put(fun.name(), fun);
+ synchronized (declared)
+ {
+ List<Function> functions = declared.get(fun.name());
+ if (functions == null)
+ {
+ functions = new CopyOnWriteArrayList<>();
+ List<Function> existing = declared.putIfAbsent(fun.name(), functions);
+ if (existing != null)
+ functions = existing;
+ }
+ functions.add(fun);
+ }
}
public static ColumnSpecification makeArgSpec(String receiverKs, String receiverCf, Function fun, int i)
{
return new ColumnSpecification(receiverKs,
receiverCf,
- new ColumnIdentifier("arg" + i + "(" + fun.name().toString().toLowerCase() + ")", true),
+ new ColumnIdentifier("arg" + i + '(' + fun.name().toString().toLowerCase() + ')', true),
fun.argTypes().get(i));
}
public static int getOverloadCount(FunctionName name)
{
- return declared.get(name).size();
+ return find(name).size();
}
/**
@@ -142,13 +155,13 @@ public abstract class Functions
// function name not fully qualified
candidates = new ArrayList<>();
// add 'SYSTEM' (native) candidates
- candidates.addAll(declared.get(name.asNativeFunction()));
+ candidates.addAll(find(name.asNativeFunction()));
// add 'current keyspace' candidates
- candidates.addAll(declared.get(new FunctionName(keyspace, name.name)));
+ candidates.addAll(find(new FunctionName(keyspace, name.name)));
}
else
// function name is fully qualified (keyspace + name)
- candidates = declared.get(name);
+ candidates = find(name);
if (candidates.isEmpty())
return null;
@@ -191,13 +204,14 @@ public abstract class Functions
public static List<Function> find(FunctionName name)
{
- return declared.get(name);
+ List<Function> functions = declared.get(name);
+ return functions != null ? functions : Collections.<Function>emptyList();
}
public static Function find(FunctionName name, List<AbstractType<?>> argTypes)
{
assert name.hasKeyspace() : "function name not fully qualified";
- for (Function f : declared.get(name))
+ for (Function f : find(name))
{
if (typeEquals(f.argTypes(), argTypes))
return f;
@@ -282,11 +296,25 @@ public abstract class Functions
}
// Same remarks than for addFunction
- public static void removeFunction(FunctionName name, List<AbstractType<?>> argsTypes)
+ public static void removeFunction(FunctionName name, List<AbstractType<?>> argTypes)
{
- Function old = find(name, argsTypes);
- assert old != null && !old.isNative();
- declared.remove(old.name(), old);
+ assert name.hasKeyspace() : "function name " + name + " not fully qualified";
+ synchronized (declared)
+ {
+ List<Function> functions = find(name);
+ for (int i = 0; i < functions.size(); i++)
+ {
+ Function f = functions.get(i);
+ if (!typeEquals(f.argTypes(), argTypes))
+ continue;
+ assert !f.isNative();
+ functions.remove(i);
+ if (functions.isEmpty())
+ declared.remove(name);
+ return;
+ }
+ assert false : "Function " + name + " not declared";
+ }
}
// Same remarks than for addFunction
@@ -299,15 +327,19 @@ public abstract class Functions
public static List<Function> getReferencesTo(Function old)
{
List<Function> references = new ArrayList<>();
- for (Function function : declared.values())
- if (function.hasReferenceTo(old))
- references.add(function);
+ for (List<Function> functions : declared.values())
+ for (Function function : functions)
+ if (function.hasReferenceTo(old))
+ references.add(function);
return references;
}
public static Collection<Function> all()
{
- return declared.values();
+ List<Function> all = new ArrayList<>();
+ for (List<Function> functions : declared.values())
+ all.addAll(functions);
+ return all;
}
public static boolean typeEquals(AbstractType<?> t1, AbstractType<?> t2)