From 4f44616ef8942b1c1501dbfb265df9298425ba88 Mon Sep 17 00:00:00 2001 From: Jonathan Ellis Date: Mon, 1 Nov 2010 22:42:31 +0000 Subject: [PATCH 1/6] fail ant gen-thrift-[py|java] if the thrift compiler signals an error. patch by mdennis; reviewed by jbellis for CASSANDRA-1692 git-svn-id: https://svn.apache.org/repos/asf/cassandra/branches/cassandra-0.7@1029872 13f79535-47bb-0310-9956-ffa450edef68 --- build.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.xml b/build.xml index a685b56cfe..746f3131a4 100644 --- a/build.xml +++ b/build.xml @@ -231,7 +231,7 @@ --> Generating Thrift Java code from ${basedir}/interface/cassandra.thrift .... - + @@ -246,7 +246,7 @@ Generating Thrift Python code from ${basedir}/interface/cassandra.thrift .... - + From 4909415a3ea35bf7807a66afbb137a6853b02c76 Mon Sep 17 00:00:00 2001 From: Jonathan Ellis Date: Tue, 2 Nov 2010 06:14:54 +0000 Subject: [PATCH 2/6] merge from 0.6 git-svn-id: https://svn.apache.org/repos/asf/cassandra/branches/cassandra-0.7@1029960 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES.txt | 2 + .../apache/cassandra/io/util/FileUtils.java | 46 ++++------------- .../cassandra/service/StorageProxy.java | 49 ++++++++++--------- .../org/apache/cassandra/utils/CLibrary.java | 20 ++++++-- .../apache/cassandra/utils/FBUtilities.java | 13 ++--- 5 files changed, 59 insertions(+), 71 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index b1a72628a7..91ceb27422 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -9,6 +9,8 @@ dev * add INTERNAL_RESPONSE verb to differentiate from responses related to client requests (CASSANDRA-1685) * log tpstats when dropping messages (CASSANDRA-1660) + * Avoid dropping messages off the client request path (CASSANDRA-1676) + * fix jna errno reporting (CASSANDRA-1694) 0.7.0-beta3 diff --git a/src/java/org/apache/cassandra/io/util/FileUtils.java b/src/java/org/apache/cassandra/io/util/FileUtils.java index ef129763db..cfb44c6178 100644 --- a/src/java/org/apache/cassandra/io/util/FileUtils.java +++ b/src/java/org/apache/cassandra/io/util/FileUtils.java @@ -18,17 +18,16 @@ package org.apache.cassandra.io.util; -import java.io.*; +import java.io.File; +import java.io.IOException; import java.text.DecimalFormat; -import java.util.*; +import java.util.Comparator; +import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.sun.jna.Native; -import org.apache.cassandra.utils.CLibrary; - -import com.sun.jna.Native; +import com.sun.jna.LastErrorException; import org.apache.cassandra.utils.CLibrary; @@ -164,29 +163,6 @@ public class FileUtils } } - /** - * calculate the total space used by a file or directory - * - * @param path the path - * @return total space used. - */ - public static long getUsedDiskSpaceForPath(String path) - { - File file = new File(path); - - if (file.isFile()) - { - return file.length(); - } - - long diskSpace = 0; - for (File childFile: file.listFiles()) - { - diskSpace += getUsedDiskSpaceForPath(childFile.getPath()); - } - return diskSpace; - } - /** * Deletes all files and subdirectories under "dir". * @param dir Directory to be deleted @@ -217,25 +193,21 @@ public class FileUtils */ public static void createHardLink(File sourceFile, File destinationFile) throws IOException { - int errno = Integer.MIN_VALUE; try { int result = CLibrary.link(sourceFile.getAbsolutePath(), destinationFile.getAbsolutePath()); - if (result != 0) - errno = Native.getLastError(); + assert result == 0; // success is always zero } catch (UnsatisfiedLinkError e) { createHardLinkWithExec(sourceFile, destinationFile); - return; } - - if (errno != Integer.MIN_VALUE) + catch (LastErrorException e) { // there are 17 different error codes listed on the man page. punt until/unless we find which // ones actually turn up in practice. - throw new IOException(String.format("Unable to create hard link from %s to %s (errno %d)", - sourceFile, destinationFile, errno)); + throw new IOException(String.format("Unable to create hard link from %s to %s (errno %d)", + sourceFile, destinationFile, CLibrary.errno(e))); } } diff --git a/src/java/org/apache/cassandra/service/StorageProxy.java b/src/java/org/apache/cassandra/service/StorageProxy.java index 90c36b45d7..7505e2d5f2 100644 --- a/src/java/org/apache/cassandra/service/StorageProxy.java +++ b/src/java/org/apache/cassandra/service/StorageProxy.java @@ -65,6 +65,7 @@ public class StorageProxy implements StorageProxyMBean private static final LatencyTracker rangeStats = new LatencyTracker(); private static final LatencyTracker writeStats = new LatencyTracker(); private static boolean hintedHandoffEnabled = DatabaseDescriptor.hintedHandoffEnabled(); + private static final String UNREACHABLE = "UNREACHABLE"; private StorageProxy() {} static @@ -491,8 +492,6 @@ public class StorageProxy implements StorageProxyMBean */ public static Map> describeSchemaVersions() { - final Map> results = new HashMap>(); - final String myVersion = DatabaseDescriptor.getDefsVersion().toString(); final Map versions = new ConcurrentHashMap(); final Set liveHosts = Gossiper.instance.getLiveMembers(); @@ -523,30 +522,34 @@ public class StorageProxy implements StorageProxyMBean logger.debug("My version is " + myVersion); - // first, indicate any hosts that did not respond. - final Set ackedHosts = versions.keySet(); - if (ackedHosts.size() < liveHosts.size()) + // maps versions to hosts that are on that version. + Map> results = new HashMap>(); + Set allHosts = new HashSet(); + allHosts.addAll(Gossiper.instance.getLiveMembers()); + allHosts.addAll(Gossiper.instance.getUnreachableMembers()); + for (InetAddress host : allHosts) { - Set missingHosts = new HashSet(liveHosts); - missingHosts.removeAll(ackedHosts); - assert missingHosts.size() > 0; - List missingHostNames = new ArrayList(missingHosts.size()); - for (InetAddress host : missingHosts) - missingHostNames.add(host.getHostAddress()); - results.put(DatabaseDescriptor.INITIAL_VERSION.toString(), missingHostNames); - logger.debug("Hosts not in agreement. Didn't get a response from everybody: " + StringUtils.join(missingHostNames, ",")); + UUID version = versions.get(host); + String stringVersion = version == null ? UNREACHABLE : version.toString(); + List hosts = results.get(stringVersion); + if (hosts == null) + { + hosts = new ArrayList(); + results.put(stringVersion, hosts); + } + hosts.add(host.getHostAddress()); + } + if (results.get(UNREACHABLE) != null) + logger.debug("Hosts not in agreement. Didn't get a response from everybody: " + StringUtils.join(results.get(UNREACHABLE), ",")); + // check for version disagreement. log the hosts that don't agree. + for (Map.Entry> entry : results.entrySet()) + { + if (entry.getKey().equals(UNREACHABLE) || entry.getKey().equals(myVersion)) + continue; + for (String host : entry.getValue()) + logger.debug("%s disagrees (%s)", host, entry.getKey()); } - // check for version disagreement. log the hosts that don't agree. - for (InetAddress host : ackedHosts) - { - String uuid = versions.get(host).toString(); - if (!results.containsKey(uuid)) - results.put(uuid, new ArrayList()); - results.get(uuid).add(host.getHostAddress()); - if (!uuid.equals(myVersion)) - logger.debug("%s disagrees (%s)", host.getHostAddress(), uuid); - } if (results.size() == 1) logger.debug("Schemas are in agreement."); diff --git a/src/java/org/apache/cassandra/utils/CLibrary.java b/src/java/org/apache/cassandra/utils/CLibrary.java index ee85a9a5d6..e0163bf013 100644 --- a/src/java/org/apache/cassandra/utils/CLibrary.java +++ b/src/java/org/apache/cassandra/utils/CLibrary.java @@ -21,6 +21,7 @@ package org.apache.cassandra.utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.sun.jna.LastErrorException; import com.sun.jna.Native; public final class CLibrary @@ -48,10 +49,23 @@ public final class CLibrary } } - public static native int mlockall(int flags); - public static native int munlockall(); + public static native int mlockall(int flags) throws LastErrorException; + public static native int munlockall() throws LastErrorException; - public static native int link(String from, String to); + public static native int link(String from, String to) throws LastErrorException; + + public static int errno(LastErrorException e) + { + try + { + return e.getErrorCode(); + } + catch (NoSuchMethodError x) + { + logger.warn("Obsolete version of JNA present; unable to read errno. Upgrade to JNA 3.2.7 or later"); + return 0; + } + } private CLibrary() {} } diff --git a/src/java/org/apache/cassandra/utils/FBUtilities.java b/src/java/org/apache/cassandra/utils/FBUtilities.java index 6d39d8cc84..0721d02d90 100644 --- a/src/java/org/apache/cassandra/utils/FBUtilities.java +++ b/src/java/org/apache/cassandra/utils/FBUtilities.java @@ -41,6 +41,7 @@ import org.apache.commons.lang.ArrayUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.sun.jna.LastErrorException; import com.sun.jna.Native; import org.apache.cassandra.config.ConfigurationException; import org.apache.cassandra.config.DatabaseDescriptor; @@ -639,22 +640,18 @@ public class FBUtilities public static void tryMlockall() { - int errno = Integer.MIN_VALUE; try { int result = CLibrary.mlockall(CLibrary.MCL_CURRENT); - if (result != 0) - errno = Native.getLastError(); + assert result == 0; // mlockall should always be zero on success } catch (UnsatisfiedLinkError e) { // this will have already been logged by CLibrary, no need to repeat it - return; } - - if (errno != Integer.MIN_VALUE) + catch (LastErrorException e) { - if (errno == CLibrary.ENOMEM && System.getProperty("os.name").toLowerCase().contains("linux")) + if (CLibrary.errno(e) == CLibrary.ENOMEM && System.getProperty("os.name").toLowerCase().contains("linux")) { logger_.warn("Unable to lock JVM memory (ENOMEM)." + " This can result in part of the JVM being swapped out, especially with mmapped I/O enabled." @@ -663,7 +660,7 @@ public class FBUtilities else if (!System.getProperty("os.name").toLowerCase().contains("mac")) { // OS X allows mlockall to be called, but always returns an error - logger_.warn("Unknown mlockall error " + errno); + logger_.warn("Unknown mlockall error " + CLibrary.errno(e)); } } } From 976ac6a1c6f5b82e6b13cedf7776f5a5feb931c6 Mon Sep 17 00:00:00 2001 From: Jonathan Ellis Date: Tue, 2 Nov 2010 16:41:54 +0000 Subject: [PATCH 3/6] revert r1028360; see CASSANDRA-1675 git-svn-id: https://svn.apache.org/repos/asf/cassandra/branches/cassandra-0.7@1030117 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/cassandra/db/ColumnFamilyStore.java | 4 ---- src/java/org/apache/cassandra/db/Memtable.java | 15 +-------------- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java index e4a09fe489..6888845eec 100644 --- a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java +++ b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java @@ -682,11 +682,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean public void forceFlushIfExpired() { if (memtable.isExpired()) - { - logger.info("Memtable for {} has reached memtable_flush_after_mins {}, enqueueing flush", - memtable.cfs.getColumnFamilyName(), memtable.cfs.getMemtableFlushAfterMins()); forceFlush(); - } } public Future forceFlush() diff --git a/src/java/org/apache/cassandra/db/Memtable.java b/src/java/org/apache/cassandra/db/Memtable.java index fbba08664a..41dc9c8847 100644 --- a/src/java/org/apache/cassandra/db/Memtable.java +++ b/src/java/org/apache/cassandra/db/Memtable.java @@ -99,20 +99,7 @@ public class Memtable implements Comparable, IFlushable boolean isThresholdViolated() { - if (currentThroughput.get() >= THRESHOLD) - { - logger.info("Memtable for CF {} has reached memtable_throughput_in_mb {}, enqueueing flush", - cfs.getColumnFamilyName(), THRESHOLD); - return true; - } - if (currentOperations.get() >= THRESHOLD_COUNT) - { - logger.info("Memtable for CF {} has reached memtable_operations_in_millions {}, enqueueing flush", - cfs.getColumnFamilyName(), THRESHOLD_COUNT); - return true; - } - // default case, threshold is not violated. - return false; + return currentThroughput.get() >= this.THRESHOLD || currentOperations.get() >= this.THRESHOLD_COUNT; } boolean isFrozen() From b5d9ac6e7c84d220995ff0103d4947b21c5d02e9 Mon Sep 17 00:00:00 2001 From: Jonathan Ellis Date: Tue, 2 Nov 2010 19:20:56 +0000 Subject: [PATCH 4/6] merge from 0.6 git-svn-id: https://svn.apache.org/repos/asf/cassandra/branches/cassandra-0.7@1030186 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES.txt | 1 + .../apache/cassandra/config/DatabaseDescriptor.java | 10 ++++++++-- src/java/org/apache/cassandra/db/Memtable.java | 4 +++- src/java/org/apache/cassandra/io/util/FileUtils.java | 4 +++- src/java/org/apache/cassandra/utils/CLibrary.java | 5 +++-- src/java/org/apache/cassandra/utils/FBUtilities.java | 4 +++- 6 files changed, 21 insertions(+), 7 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 91ceb27422..de6d86486e 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -11,6 +11,7 @@ dev * log tpstats when dropping messages (CASSANDRA-1660) * Avoid dropping messages off the client request path (CASSANDRA-1676) * fix jna errno reporting (CASSANDRA-1694) + * add friendlier error for UnknownHostException on startup (CASSANDRA-1697) 0.7.0-beta3 diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java index 5e06047f97..0af62bdfb7 100644 --- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java +++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java @@ -367,11 +367,17 @@ public class DatabaseDescriptor { throw new ConfigurationException("seeds missing; a minimum of one seed is required."); } - for( int i = 0; i < conf.seeds.length; ++i ) + for (String seedString : conf.seeds) { - seeds.add(InetAddress.getByName(conf.seeds[i])); + seeds.add(InetAddress.getByName(seedString)); } } + catch (UnknownHostException e) + { + logger.error("Fatal error: " + e.getMessage()); + System.err.println("Unable to start with unknown hosts configured. Use IP addresses instead of hostnames."); + System.exit(2); + } catch (ConfigurationException e) { logger.error("Fatal error: " + e.getMessage()); diff --git a/src/java/org/apache/cassandra/db/Memtable.java b/src/java/org/apache/cassandra/db/Memtable.java index 41dc9c8847..a524ff3d00 100644 --- a/src/java/org/apache/cassandra/db/Memtable.java +++ b/src/java/org/apache/cassandra/db/Memtable.java @@ -18,6 +18,7 @@ package org.apache.cassandra.db; +import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; import java.util.Collection; @@ -158,7 +159,8 @@ public class Memtable implements Comparable, IFlushable writer.append(entry.getKey(), entry.getValue()); SSTableReader ssTable = writer.closeAndOpenReader(); - logger.info("Completed flushing " + ssTable.getFilename()); + logger.info(String.format("Completed flushing %s (%d bytes)", + ssTable.getFilename(), new File(ssTable.getFilename()).length())); return ssTable; } diff --git a/src/java/org/apache/cassandra/io/util/FileUtils.java b/src/java/org/apache/cassandra/io/util/FileUtils.java index cfb44c6178..6e505a3e8b 100644 --- a/src/java/org/apache/cassandra/io/util/FileUtils.java +++ b/src/java/org/apache/cassandra/io/util/FileUtils.java @@ -202,8 +202,10 @@ public class FileUtils { createHardLinkWithExec(sourceFile, destinationFile); } - catch (LastErrorException e) + catch (RuntimeException e) { + if (!(e instanceof LastErrorException)) + throw e; // there are 17 different error codes listed on the man page. punt until/unless we find which // ones actually turn up in practice. throw new IOException(String.format("Unable to create hard link from %s to %s (errno %d)", diff --git a/src/java/org/apache/cassandra/utils/CLibrary.java b/src/java/org/apache/cassandra/utils/CLibrary.java index e0163bf013..f3155b675b 100644 --- a/src/java/org/apache/cassandra/utils/CLibrary.java +++ b/src/java/org/apache/cassandra/utils/CLibrary.java @@ -54,11 +54,12 @@ public final class CLibrary public static native int link(String from, String to) throws LastErrorException; - public static int errno(LastErrorException e) + public static int errno(RuntimeException e) { + assert e instanceof LastErrorException; try { - return e.getErrorCode(); + return ((LastErrorException) e).getErrorCode(); } catch (NoSuchMethodError x) { diff --git a/src/java/org/apache/cassandra/utils/FBUtilities.java b/src/java/org/apache/cassandra/utils/FBUtilities.java index 0721d02d90..fce078d893 100644 --- a/src/java/org/apache/cassandra/utils/FBUtilities.java +++ b/src/java/org/apache/cassandra/utils/FBUtilities.java @@ -649,8 +649,10 @@ public class FBUtilities { // this will have already been logged by CLibrary, no need to repeat it } - catch (LastErrorException e) + catch (RuntimeException e) { + if (!(e instanceof LastErrorException)) + throw e; if (CLibrary.errno(e) == CLibrary.ENOMEM && System.getProperty("os.name").toLowerCase().contains("linux")) { logger_.warn("Unable to lock JVM memory (ENOMEM)." From 6c9c56fc4e08619b50fc337d89835361742cdd79 Mon Sep 17 00:00:00 2001 From: Jonathan Ellis Date: Tue, 2 Nov 2010 23:25:26 +0000 Subject: [PATCH 5/6] include jna dependency in RPM package. patch by Nick Bailey; reviewed by jbellis for CASSANDRA-1690 git-svn-id: https://svn.apache.org/repos/asf/cassandra/branches/cassandra-0.7@1030284 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES.txt | 1 + redhat/apache-cassandra.spec | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index de6d86486e..406eb2431a 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -12,6 +12,7 @@ dev * Avoid dropping messages off the client request path (CASSANDRA-1676) * fix jna errno reporting (CASSANDRA-1694) * add friendlier error for UnknownHostException on startup (CASSANDRA-1697) + * include jna dependency in RPM package (CASSANDRA-1690) 0.7.0-beta3 diff --git a/redhat/apache-cassandra.spec b/redhat/apache-cassandra.spec index 666cc4a2f5..4a9813e7d3 100644 --- a/redhat/apache-cassandra.spec +++ b/redhat/apache-cassandra.spec @@ -19,6 +19,7 @@ BuildRequires: ant BuildRequires: ant-nodeps Requires: java >= 1.6.0 +Requires: jna >= 3.2.7 Requires: jpackage-utils Requires(pre): user(cassandra) Requires(pre): group(cassandra) From 85d6ce67f3b57eb95444ae631841f460617e64a0 Mon Sep 17 00:00:00 2001 From: Jonathan Ellis Date: Tue, 2 Nov 2010 23:32:39 +0000 Subject: [PATCH 6/6] merge from 0.6 git-svn-id: https://svn.apache.org/repos/asf/cassandra/branches/cassandra-0.7@1030285 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES.txt | 1 + contrib/py_stress/stress.py | 5 +- .../cassandra/db/ColumnFamilyStore.java | 78 +++---------- .../apache/cassandra/io/util/FileUtils.java | 62 ---------- .../service/AbstractCassandraDaemon.java | 3 +- .../cassandra/thrift/CassandraDaemon.java | 2 +- .../org/apache/cassandra/utils/CLibrary.java | 108 ++++++++++++++++-- .../apache/cassandra/utils/FBUtilities.java | 29 ----- 8 files changed, 122 insertions(+), 166 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 406eb2431a..7b189ffc91 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -13,6 +13,7 @@ dev * fix jna errno reporting (CASSANDRA-1694) * add friendlier error for UnknownHostException on startup (CASSANDRA-1697) * include jna dependency in RPM package (CASSANDRA-1690) + * add --skip-keys option to stress.py (CASSANDRA-1696) 0.7.0-beta3 diff --git a/contrib/py_stress/stress.py b/contrib/py_stress/stress.py index 3ab4d3cd9c..67adf72915 100644 --- a/contrib/py_stress/stress.py +++ b/contrib/py_stress/stress.py @@ -61,6 +61,8 @@ except ImportError: parser = OptionParser() parser.add_option('-n', '--num-keys', type="int", dest="numkeys", help="Number of keys", default=1000**2) +parser.add_option('-N', '--skip-keys', type="float", dest="skipkeys", + help="Fraction of keys to skip initially", default=0) parser.add_option('-t', '--threads', type="int", dest="threads", help="Number of threads/procs to use", default=50) parser.add_option('-c', '--columns', type="int", dest="columns", @@ -189,7 +191,8 @@ class Operation(Thread): def __init__(self, i, opcounts, keycounts, latencies): Thread.__init__(self) # generator of the keys to be used - self.range = xrange(keys_per_thread * i, keys_per_thread * (i + 1)) + self.range = xrange(int(keys_per_thread * (i + options.skipkeys)), + keys_per_thread * (i + 1)) # we can't use a local counter, since that won't be visible to the parent # under multiprocessing. instead, the parent passes a "opcounts" array # and an index that is our assigned counter. diff --git a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java index 6888845eec..603f69a808 100644 --- a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java +++ b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java @@ -18,46 +18,22 @@ package org.apache.cassandra.db; -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FilenameFilter; -import java.io.IOError; -import java.io.IOException; -import java.io.ObjectInputStream; +import java.io.*; import java.lang.management.ManagementFactory; import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedMap; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.concurrent.ConcurrentSkipListMap; -import java.util.concurrent.ConcurrentSkipListSet; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; +import java.util.*; +import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Pattern; - import javax.management.MBeanServer; import javax.management.ObjectName; +import com.google.common.collect.Iterables; +import org.apache.commons.collections.IteratorUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import org.apache.cassandra.concurrent.JMXEnabledThreadPoolExecutor; import org.apache.cassandra.concurrent.NamedThreadFactory; import org.apache.cassandra.concurrent.RetryingScheduledThreadPoolExecutor; @@ -66,47 +42,20 @@ import org.apache.cassandra.config.CFMetaData; import org.apache.cassandra.config.ColumnDefinition; import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.db.columniterator.IColumnIterator; -import org.apache.cassandra.db.columniterator.IdentityQueryFilter; import org.apache.cassandra.db.commitlog.CommitLog; import org.apache.cassandra.db.commitlog.CommitLogSegment; -import org.apache.cassandra.db.filter.IFilter; -import org.apache.cassandra.db.filter.NamesQueryFilter; -import org.apache.cassandra.db.filter.QueryFilter; -import org.apache.cassandra.db.filter.QueryPath; -import org.apache.cassandra.db.filter.SliceQueryFilter; +import org.apache.cassandra.db.filter.*; import org.apache.cassandra.db.marshal.AbstractType; import org.apache.cassandra.db.marshal.BytesType; import org.apache.cassandra.db.marshal.LocalByPartionerType; -import org.apache.cassandra.dht.AbstractBounds; -import org.apache.cassandra.dht.Bounds; -import org.apache.cassandra.dht.ByteOrderedPartitioner; -import org.apache.cassandra.dht.IPartitioner; -import org.apache.cassandra.dht.LocalPartitioner; -import org.apache.cassandra.dht.LocalToken; -import org.apache.cassandra.dht.OrderPreservingPartitioner; -import org.apache.cassandra.dht.Range; -import org.apache.cassandra.dht.Token; -import org.apache.cassandra.io.sstable.Component; -import org.apache.cassandra.io.sstable.Descriptor; -import org.apache.cassandra.io.sstable.ReducingKeyIterator; -import org.apache.cassandra.io.sstable.SSTable; -import org.apache.cassandra.io.sstable.SSTableReader; -import org.apache.cassandra.io.sstable.SSTableTracker; +import org.apache.cassandra.dht.*; +import org.apache.cassandra.io.sstable.*; import org.apache.cassandra.io.util.FileUtils; import org.apache.cassandra.service.StorageService; import org.apache.cassandra.thrift.IndexClause; import org.apache.cassandra.thrift.IndexExpression; import org.apache.cassandra.thrift.IndexOperator; -import org.apache.cassandra.utils.EstimatedHistogram; -import org.apache.cassandra.utils.FBUtilities; -import org.apache.cassandra.utils.LatencyTracker; -import org.apache.cassandra.utils.Pair; -import org.apache.cassandra.utils.WrappedRunnable; -import org.apache.commons.collections.IteratorUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.collect.Iterables; +import org.apache.cassandra.utils.*; public class ColumnFamilyStore implements ColumnFamilyStoreMBean { @@ -1536,7 +1485,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean { File sourceFile = new File(ssTable.descriptor.filenameFor(component)); File targetLink = new File(snapshotDirectoryPath, sourceFile.getName()); - FileUtils.createHardLink(sourceFile, targetLink); + CLibrary.createHardLink(sourceFile, targetLink); } if (logger.isDebugEnabled()) logger.debug("Snapshot for " + table + " keyspace data file " + ssTable.getFilename() + @@ -1546,7 +1495,6 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean { throw new IOError(e); } - } } diff --git a/src/java/org/apache/cassandra/io/util/FileUtils.java b/src/java/org/apache/cassandra/io/util/FileUtils.java index 6e505a3e8b..e2ca78c8ce 100644 --- a/src/java/org/apache/cassandra/io/util/FileUtils.java +++ b/src/java/org/apache/cassandra/io/util/FileUtils.java @@ -182,66 +182,4 @@ public class FileUtils // The directory is now empty so now it can be smoked deleteWithConfirm(dir); } - - /** - * Create a hard link for a given file. - * - * @param sourceFile The name of the source file. - * @param destinationFile The name of the destination file. - * - * @throws IOException if an error has occurred while creating the link. - */ - public static void createHardLink(File sourceFile, File destinationFile) throws IOException - { - try - { - int result = CLibrary.link(sourceFile.getAbsolutePath(), destinationFile.getAbsolutePath()); - assert result == 0; // success is always zero - } - catch (UnsatisfiedLinkError e) - { - createHardLinkWithExec(sourceFile, destinationFile); - } - catch (RuntimeException e) - { - if (!(e instanceof LastErrorException)) - throw e; - // there are 17 different error codes listed on the man page. punt until/unless we find which - // ones actually turn up in practice. - throw new IOException(String.format("Unable to create hard link from %s to %s (errno %d)", - sourceFile, destinationFile, CLibrary.errno(e))); - } - } - - private static void createHardLinkWithExec(File sourceFile, File destinationFile) throws IOException - { - String osname = System.getProperty("os.name"); - ProcessBuilder pb; - if (osname.startsWith("Windows")) - { - float osversion = Float.parseFloat(System.getProperty("os.version")); - if (osversion >= 6.0f) - { - pb = new ProcessBuilder("cmd", "/c", "mklink", "/H", destinationFile.getAbsolutePath(), sourceFile.getAbsolutePath()); - } - else - { - pb = new ProcessBuilder("fsutil", "hardlink", "create", destinationFile.getAbsolutePath(), sourceFile.getAbsolutePath()); - } - } - else - { - pb = new ProcessBuilder("ln", sourceFile.getAbsolutePath(), destinationFile.getAbsolutePath()); - pb.redirectErrorStream(true); - } - Process p = pb.start(); - try - { - p.waitFor(); - } - catch (InterruptedException e) - { - throw new RuntimeException(e); - } - } } diff --git a/src/java/org/apache/cassandra/service/AbstractCassandraDaemon.java b/src/java/org/apache/cassandra/service/AbstractCassandraDaemon.java index ade26b4cbd..62f20202ff 100644 --- a/src/java/org/apache/cassandra/service/AbstractCassandraDaemon.java +++ b/src/java/org/apache/cassandra/service/AbstractCassandraDaemon.java @@ -39,6 +39,7 @@ import org.apache.cassandra.db.SystemTable; import org.apache.cassandra.db.Table; import org.apache.cassandra.db.commitlog.CommitLog; import org.apache.cassandra.db.migration.Migration; +import org.apache.cassandra.utils.CLibrary; import org.apache.cassandra.utils.FBUtilities; import org.apache.cassandra.utils.Mx4jTool; import org.mortbay.thread.ThreadPool; @@ -70,7 +71,7 @@ public abstract class AbstractCassandraDaemon implements CassandraDaemon protected void setup() throws IOException { logger.info("Heap size: {}/{}", Runtime.getRuntime().totalMemory(), Runtime.getRuntime().maxMemory()); - FBUtilities.tryMlockall(); + CLibrary.tryMlockall(); listenPort = DatabaseDescriptor.getRpcPort(); listenAddr = DatabaseDescriptor.getRpcAddress(); diff --git a/src/java/org/apache/cassandra/thrift/CassandraDaemon.java b/src/java/org/apache/cassandra/thrift/CassandraDaemon.java index f54590811e..ed0b4b440a 100644 --- a/src/java/org/apache/cassandra/thrift/CassandraDaemon.java +++ b/src/java/org/apache/cassandra/thrift/CassandraDaemon.java @@ -52,7 +52,7 @@ public class CassandraDaemon extends org.apache.cassandra.service.AbstractCassan protected void setup() throws IOException { - super.setup(); + super.setup(); // now we start listening for clients final CassandraServer cassandraServer = new CassandraServer(); diff --git a/src/java/org/apache/cassandra/utils/CLibrary.java b/src/java/org/apache/cassandra/utils/CLibrary.java index f3155b675b..4987d9d14f 100644 --- a/src/java/org/apache/cassandra/utils/CLibrary.java +++ b/src/java/org/apache/cassandra/utils/CLibrary.java @@ -18,6 +18,9 @@ */ package org.apache.cassandra.utils; +import java.io.File; +import java.io.IOException; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,10 +31,10 @@ public final class CLibrary { private static Logger logger = LoggerFactory.getLogger(CLibrary.class); - public static final int MCL_CURRENT = 1; - public static final int MCL_FUTURE = 2; + private static final int MCL_CURRENT = 1; + private static final int MCL_FUTURE = 2; - public static final int ENOMEM = 12; + private static final int ENOMEM = 12; static { @@ -49,12 +52,12 @@ public final class CLibrary } } - public static native int mlockall(int flags) throws LastErrorException; - public static native int munlockall() throws LastErrorException; + private static native int mlockall(int flags) throws LastErrorException; + private static native int munlockall() throws LastErrorException; - public static native int link(String from, String to) throws LastErrorException; + private static native int link(String from, String to) throws LastErrorException; - public static int errno(RuntimeException e) + private static int errno(RuntimeException e) { assert e instanceof LastErrorException; try @@ -69,4 +72,95 @@ public final class CLibrary } private CLibrary() {} + + public static void tryMlockall() + { + try + { + int result = mlockall(MCL_CURRENT); + assert result == 0; // mlockall should always be zero on success + } + catch (UnsatisfiedLinkError e) + { + // this will have already been logged by CLibrary, no need to repeat it + } + catch (RuntimeException e) + { + if (!(e instanceof LastErrorException)) + throw e; + if (errno(e) == ENOMEM && System.getProperty("os.name").toLowerCase().contains("linux")) + { + logger.warn("Unable to lock JVM memory (ENOMEM)." + + " This can result in part of the JVM being swapped out, especially with mmapped I/O enabled." + + " Increase RLIMIT_MEMLOCK or run Cassandra as root."); + } + else if (!System.getProperty("os.name").toLowerCase().contains("mac")) + { + // OS X allows mlockall to be called, but always returns an error + logger.warn("Unknown mlockall error " + errno(e)); + } + } + } + + /** + * Create a hard link for a given file. + * + * @param sourceFile The name of the source file. + * @param destinationFile The name of the destination file. + * + * @throws java.io.IOException if an error has occurred while creating the link. + */ + public static void createHardLink(File sourceFile, File destinationFile) throws IOException + { + try + { + int result = link(sourceFile.getAbsolutePath(), destinationFile.getAbsolutePath()); + assert result == 0; // success is always zero + } + catch (UnsatisfiedLinkError e) + { + createHardLinkWithExec(sourceFile, destinationFile); + } + catch (RuntimeException e) + { + if (!(e instanceof LastErrorException)) + throw e; + // there are 17 different error codes listed on the man page. punt until/unless we find which + // ones actually turn up in practice. + throw new IOException(String.format("Unable to create hard link from %s to %s (errno %d)", + sourceFile, destinationFile, errno(e))); + } + } + + private static void createHardLinkWithExec(File sourceFile, File destinationFile) throws IOException + { + String osname = System.getProperty("os.name"); + ProcessBuilder pb; + if (osname.startsWith("Windows")) + { + float osversion = Float.parseFloat(System.getProperty("os.version")); + if (osversion >= 6.0f) + { + pb = new ProcessBuilder("cmd", "/c", "mklink", "/H", destinationFile.getAbsolutePath(), sourceFile.getAbsolutePath()); + } + else + { + pb = new ProcessBuilder("fsutil", "hardlink", "create", destinationFile.getAbsolutePath(), sourceFile.getAbsolutePath()); + } + } + else + { + pb = new ProcessBuilder("ln", sourceFile.getAbsolutePath(), destinationFile.getAbsolutePath()); + pb.redirectErrorStream(true); + } + Process p = pb.start(); + try + { + p.waitFor(); + } + catch (InterruptedException e) + { + throw new RuntimeException(e); + } + } } diff --git a/src/java/org/apache/cassandra/utils/FBUtilities.java b/src/java/org/apache/cassandra/utils/FBUtilities.java index fce078d893..082bc5c569 100644 --- a/src/java/org/apache/cassandra/utils/FBUtilities.java +++ b/src/java/org/apache/cassandra/utils/FBUtilities.java @@ -638,35 +638,6 @@ public class FBUtilities } } - public static void tryMlockall() - { - try - { - int result = CLibrary.mlockall(CLibrary.MCL_CURRENT); - assert result == 0; // mlockall should always be zero on success - } - catch (UnsatisfiedLinkError e) - { - // this will have already been logged by CLibrary, no need to repeat it - } - catch (RuntimeException e) - { - if (!(e instanceof LastErrorException)) - throw e; - if (CLibrary.errno(e) == CLibrary.ENOMEM && System.getProperty("os.name").toLowerCase().contains("linux")) - { - logger_.warn("Unable to lock JVM memory (ENOMEM)." - + " This can result in part of the JVM being swapped out, especially with mmapped I/O enabled." - + " Increase RLIMIT_MEMLOCK or run Cassandra as root."); - } - else if (!System.getProperty("os.name").toLowerCase().contains("mac")) - { - // OS X allows mlockall to be called, but always returns an error - logger_.warn("Unknown mlockall error " + CLibrary.errno(e)); - } - } - } - public static SortedSet singleton(T column) { return new TreeSet(Arrays.asList(column));