diff --git a/CHANGES.txt b/CHANGES.txt index 5c3521b27a..6c45c466f5 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -58,13 +58,18 @@ on create/update of the ColumnFamily and CQL 'ALTER' statement (CASSANDRA-3036) * return an InvalidRequestException if an indexed column is assigned a value larger than 64KB (CASSANDRA-3057) - * fix of numeric-only and string column names handling in CLI "drop index" (CASSANDRA-3054) + * fix of numeric-only and string column names handling in CLI "drop index" + (CASSANDRA-3054) * prune index scan resultset back to original request for lazy resultset expansion case (CASSANDRA-2964) * (Hadoop) fail jobs when Cassandra node has failed but TaskTracker has not (CASSANDRA-2388) * fix dynamic snitch ignoring nodes when read_repair_chance is zero (CASSANDRA-2662) + * avoid retaining references to dropped CFS objects in + CompactionManager.estimatedCompactions (CASSANDRA-2708) + * expose rpc timeouts per host in MessagingServiceMBean (CASSANDRA-2941) + * avoid including cwd in classpath for deb and rpm packages (CASSANDRA-2881) 0.8.4 diff --git a/debian/cassandra.in.sh b/debian/cassandra.in.sh index 5e45b520d4..f618895b68 100644 --- a/debian/cassandra.in.sh +++ b/debian/cassandra.in.sh @@ -5,7 +5,11 @@ CASSANDRA_CONF=/etc/cassandra CASSANDRA_HOME=/usr/share/cassandra # The java classpath (required) -CLASSPATH=$CASSANDRA_CONF +if [ -n "$CLASSPATH" ]; then + CLASSPATH=$CLASSPATH:$CASSANDRA_CONF +else + CLASSPATH=$CASSANDRA_CONF +fi for jar in /usr/share/cassandra/lib/*.jar; do CLASSPATH=$CLASSPATH:$jar diff --git a/redhat/cassandra.in.sh b/redhat/cassandra.in.sh index 49b90e74d0..fcb188ea4f 100644 --- a/redhat/cassandra.in.sh +++ b/redhat/cassandra.in.sh @@ -2,11 +2,16 @@ # The directory where Cassandra's configs live (required) CASSANDRA_CONF=/etc/cassandra/conf +# The java classpath (required) +if [ -n "$CLASSPATH" ]; then + CLASSPATH=$CLASSPATH:$CASSANDRA_CONF +else + CLASSPATH=$CASSANDRA_CONF +fi + # use JNA if installed in standard location [ -r /usr/share/java/jna.jar ] && CLASSPATH="$CLASSPATH:/usr/share/java/jna.jar" -# The java classpath (required) -CLASSPATH=$CLASSPATH:$CASSANDRA_CONF for jar in /usr/share/cassandra/lib/*.jar; do CLASSPATH=$CLASSPATH:$jar diff --git a/src/java/org/apache/cassandra/net/MessagingService.java b/src/java/org/apache/cassandra/net/MessagingService.java index dd53a3e7c8..79aff111e3 100644 --- a/src/java/org/apache/cassandra/net/MessagingService.java +++ b/src/java/org/apache/cassandra/net/MessagingService.java @@ -29,6 +29,7 @@ import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; import javax.management.MBeanServer; import javax.management.ObjectName; @@ -102,6 +103,10 @@ public final class MessagingService implements MessagingServiceMBean private final Map lastDropped = Collections.synchronizedMap(new EnumMap(StorageService.Verb.class)); private final Map lastDroppedInternal = new EnumMap(StorageService.Verb.class); + private long totalTimeouts = 0; + private long recentTotalTimeouts = 0; + private final Map timeoutsPerHost = new HashMap(); + private final Map recentTimeoutsPerHost = new HashMap(); private final List subscribers = new ArrayList(); private static final long DEFAULT_CALLBACK_TIMEOUT = (long) (1.1 * DatabaseDescriptor.getRpcTimeout()); @@ -141,6 +146,17 @@ public final class MessagingService implements MessagingServiceMBean { Pair expiredValue = pair.right; maybeAddLatency(expiredValue.right, expiredValue.left, (double) DatabaseDescriptor.getRpcTimeout()); + totalTimeouts++; + String ip = expiredValue.left.getHostAddress(); + AtomicLong c = timeoutsPerHost.get(ip); + if (c == null) + c = timeoutsPerHost.put(ip, new AtomicLong()); + c.incrementAndGet(); + // we only create AtomicLong instances here, so that the write + // access to the hashmap happens single-threadedly. + if (recentTimeoutsPerHost.get(ip) == null) + recentTimeoutsPerHost.put(ip, new AtomicLong()); + return null; } }; @@ -649,4 +665,39 @@ public final class MessagingService implements MessagingServiceMBean } return map; } + + public long getTotalTimeouts() + { + return totalTimeouts; + } + + public long getRecentTotalTimouts() + { + long recent = totalTimeouts - recentTotalTimeouts; + recentTotalTimeouts = totalTimeouts; + return recent; + } + + public Map getTimeoutsPerHost() + { + Map result = new HashMap(); + for (Map.Entry entry: timeoutsPerHost.entrySet()) + { + result.put(entry.getKey(), entry.getValue().get()); + } + return result; + } + + public Map getRecentTimeoutsPerHost() + { + Map result = new HashMap(); + for (Map.Entry entry: recentTimeoutsPerHost.entrySet()) + { + String ip = entry.getKey(); + AtomicLong recent = entry.getValue(); + Long timeout = timeoutsPerHost.get(ip).get(); + result.put(ip, timeout - recent.getAndSet(timeout)); + } + return result; + } } diff --git a/src/java/org/apache/cassandra/net/MessagingServiceMBean.java b/src/java/org/apache/cassandra/net/MessagingServiceMBean.java index 1ce69fc65f..af9d5f59c9 100644 --- a/src/java/org/apache/cassandra/net/MessagingServiceMBean.java +++ b/src/java/org/apache/cassandra/net/MessagingServiceMBean.java @@ -59,4 +59,24 @@ public interface MessagingServiceMBean * dropped message counts since last called */ public Map getRecentlyDroppedMessages(); + + /** + * Total number of timeouts happened on this node + */ + public long getTotalTimeouts(); + + /** + * Number of timeouts per host + */ + public Map getTimeoutsPerHost(); + + /** + * Number of timeouts since last check. + */ + public long getRecentTotalTimouts(); + + /** + * Number of timeouts since last check per host. + */ + public Map getRecentTimeoutsPerHost(); } diff --git a/src/java/org/apache/cassandra/tools/NodeCmd.java b/src/java/org/apache/cassandra/tools/NodeCmd.java index e2b0a8dfd0..14e5991791 100644 --- a/src/java/org/apache/cassandra/tools/NodeCmd.java +++ b/src/java/org/apache/cassandra/tools/NodeCmd.java @@ -739,11 +739,19 @@ public class NodeCmd private static void handleSnapshots(NodeCommand nc, String tag, String[] cmdArgs, NodeProbe probe) throws InterruptedException, IOException { - int length = cmdArgs.length > 1 ? cmdArgs.length - 1 : 0; - String[] keyspaces = new String[length]; - for (int i = 0; i < keyspaces.length; i++) - keyspaces[i] = cmdArgs[i + 1]; - + String[] keyspaces = Arrays.copyOfRange(cmdArgs, 0, cmdArgs.length); + System.out.print("Requested snapshot for: "); + if ( keyspaces.length > 0 ) + { + for (int i = 0; i < keyspaces.length; i++) + System.out.print(keyspaces[i] + " "); + } + else + { + System.out.print("all keyspaces"); + } + System.out.println(); + switch (nc) { case SNAPSHOT :