diff --git a/lcp/pom.xml b/lcp/pom.xml new file mode 100644 index 000000000..29a9164c7 --- /dev/null +++ b/lcp/pom.xml @@ -0,0 +1,152 @@ + + 4.0.0 + + me.prettyprint + hector + 1.0-4-SNAPSHOT + + hector-lcp + jar + hector-lcp + + + me.prettyprint.hector-lcp + me.prettyprint + + + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.1 + + + + java + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + always + -Xmx512M -Xms512M -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 + + + + + + + commons-lang + commons-lang + + + commons-pool + commons-pool + + + org.apache.cassandra + cassandra-thrift + + + org.apache.thrift + libthrift + 0.6.1 + + + org.apache.cassandra + cassandra-all + + + com.google.guava + guava + + + org.slf4j + slf4j-api + + + com.github.stephenc.eaio-uuid + uuid + + + com.ecyrd.speed4j + speed4j + + + me.prettyprint + hector-core + ${pom.version} + + + + me.prettyprint + hector-test + ${pom.version} + test + + + + junit + junit + test + + + com.github.stephenc + jamm + test + + + org.mockito + mockito-all + test + + + org.slf4j + slf4j-log4j12 + test + + + org.slf4j + jcl-over-slf4j + test + + + org.slf4j + jul-to-slf4j + test + + + org.springframework + spring-beans + ${org.springframework.version} + test + + + org.springframework + spring-context + ${org.springframework.version} + test + + + commons-logging + commons-logging + + + + + org.springframework + spring-test + ${org.springframework.version} + test + + + diff --git a/lcp/src/main/java/me/prettyprint/lcp/CassandraProxyClient.java b/lcp/src/main/java/me/prettyprint/lcp/CassandraProxyClient.java new file mode 100644 index 000000000..ec8e0e812 --- /dev/null +++ b/lcp/src/main/java/me/prettyprint/lcp/CassandraProxyClient.java @@ -0,0 +1,122 @@ +/** + * 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 me.prettyprint.lcp; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.InetSocketAddress; +import java.util.Arrays; +import java.util.List; +import java.util.Random; + +import org.apache.cassandra.config.KSMetaData; +import org.apache.cassandra.thrift.*; +import org.apache.log4j.Logger; +import org.apache.thrift.TException; +import org.apache.thrift.transport.*; + + +/** + * This wraps the underlying Cassandra thrift client and attempts to handle + * disconnect, unavailable, timeout errors gracefully. + *

+ * On disconnect, if it cannot reconnect to the same host then it will use a + * different host from the ring. After a successful connecting, the ring will be + * refreshed. + *

+ * This incorporates the CircuitBreaker pattern so not to overwhelm the network + * with reconnect attempts. + */ +public class CassandraProxyClient implements java.lang.reflect.InvocationHandler { + + private static final Logger logger = Logger.getLogger(CassandraProxyClient.class); + + public enum ConnectionStrategy { + RANDOM, ROUND_ROBIN, STICKY + } + + private String host; + private int port; + + private Cassandra.Client client; + + /** + * Build the Cassandra.Iface proxy + * + * @param host cassandra host + * @param port cassandra port + * @return a Casandra.Client Interface + * @throws IOException + */ + public static Cassandra.Iface newProxyConnection(String host, int port) + throws IOException { + return (Cassandra.Iface) java.lang.reflect.Proxy.newProxyInstance(Cassandra.Client.class.getClassLoader(), + Cassandra.Client.class.getInterfaces(), new CassandraProxyClient(host, port)); + } + + /** + * Create connection to a given host. + * + * @return cassandra thrift client + * @throws IOException error + */ + public Cassandra.Client createConnection() throws IOException { + TSocket socket = new TSocket(host, port, 10000); + TTransport trans; + try { + socket.getSocket().setKeepAlive(true); + socket.getSocket().setSoLinger(false,0); + socket.getSocket().setTcpNoDelay(true); + + trans = new TFastFramedTransport(socket); + trans.open(); + + return new Cassandra.Client(new TBinaryProtocol(trans)); + + } catch (Exception e) { + throw new IOException("unable to connect to server", e); + } + + } + + private CassandraProxyClient(String host, int port) throws IOException { + this.host = host; + this.port = port; + } + + + + public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { + Object result = null; + try { + this.client = createConnection(); + result = m.invoke(client, args); + + return result; + + } catch (Exception e) { + logger.error("Error invoking a method via proxy: ", e); + throw new RuntimeException(e); + } + + } + + +} + diff --git a/lcp/src/main/java/me/prettyprint/lcp/EmbeddedServerLauncher.java b/lcp/src/main/java/me/prettyprint/lcp/EmbeddedServerLauncher.java new file mode 100644 index 000000000..9243574cf --- /dev/null +++ b/lcp/src/main/java/me/prettyprint/lcp/EmbeddedServerLauncher.java @@ -0,0 +1,90 @@ +package me.prettyprint.lcp; + +import org.apache.cassandra.config.ConfigurationException; +import org.apache.cassandra.config.DatabaseDescriptor; +import org.apache.cassandra.db.commitlog.CommitLog; +import org.apache.cassandra.thrift.CassandraDaemon; +import org.apache.thrift.transport.TTransportException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +/** + * @author zznate + */ +public class EmbeddedServerLauncher { + private static Logger log = LoggerFactory.getLogger(EmbeddedServerLauncher.class); + + private static final String CASS_ROOT = "cassandra"; + + private final String yamlFile; + static LcpCassandraDaemon cassandraDaemon; + + public EmbeddedServerLauncher() { + this("/cassandra.yaml"); + } + + public EmbeddedServerLauncher(String yamlFile) { + this.yamlFile = yamlFile; + } + + static ExecutorService executor = Executors.newSingleThreadExecutor(); + + /** + * Set embedded cassandra up and spawn it in a new thread. + * + * @throws org.apache.thrift.transport.TTransportException + * @throws java.io.IOException + * @throws InterruptedException + */ + public void setup() throws TTransportException, IOException, + InterruptedException, ConfigurationException { + if ( cassandraDaemon != null && cassandraDaemon.isRPCServerRunning() ) { + return; + } + System.setProperty("cassandra-foreground","true"); + DatabaseDescriptor.createAllDirectories(); + + log.info("Starting executor"); + + executor.execute(new CassandraRunner()); + log.info("Started executor"); + try + { + TimeUnit.SECONDS.sleep(3); + log.info("Done sleeping"); + } + catch (InterruptedException e) + { + throw new AssertionError(e); + } + } + + public static void teardown() { + try { + CommitLog.instance.shutdownBlocking(); + } catch (Exception e) { + e.printStackTrace(); + } + executor.shutdown(); + executor.shutdownNow(); + log.info("Teardown complete"); + } + + + class CassandraRunner implements Runnable { + + public void run() { + + cassandraDaemon = new LcpCassandraDaemon(); + + cassandraDaemon.activate(); + + } + + } +} diff --git a/lcp/src/main/java/me/prettyprint/lcp/LcpCassandraServer.java b/lcp/src/main/java/me/prettyprint/lcp/LcpCassandraServer.java new file mode 100644 index 000000000..f634c5227 --- /dev/null +++ b/lcp/src/main/java/me/prettyprint/lcp/LcpCassandraServer.java @@ -0,0 +1,227 @@ +package me.prettyprint.lcp; + +import me.prettyprint.cassandra.service.ThriftCluster; +import me.prettyprint.hector.api.Cluster; +import me.prettyprint.hector.api.factory.HFactory; +import org.apache.cassandra.thrift.*; +import org.apache.thrift.TException; +import org.apache.thrift.transport.TFramedTransport; +import org.apache.thrift.transport.TSocket; +import org.apache.thrift.transport.TTransport; +import org.apache.thrift.transport.TTransportException; + +import java.net.SocketException; +import java.nio.ByteBuffer; +import java.util.List; +import java.util.Map; + +/** + * @author zznate + */ +public class LcpCassandraServer implements Cassandra.Iface { + + /* + general contract for each method: + - acquire Cassandra.Client from pool, pass through + - if method uses a key, check the token cache & route + + */ + + + public LcpCassandraServer() { + + } + /** + * Use the key to deduce locality for "client-mediated selects" + * + * @return + */ + protected Cassandra.Client acquire() { + // DecoratedKey dk = StorageService.getPartitioner().decorateKey(key); + // ~ in the case of RP, is just: return new BigIntegerToken(FBUtilities.hashToBigInteger(key)); + // --- leads to --- + // from RandomPartitioner#getToken(bb key): return new BigIntegerToken(FBUtilities.hashToBigInteger(key)); + // + // really just need to query describe_ring and store the output + // - model after locator.TokenMetadata? Use TokenMetadata directly + // - TokenRange from describe_ring has everything, but may not want to convert BB to strings + // * make a local version which uses Token/TokenMetadata directly + // * see TokenMetadata ctor for this + Cassandra.Client client; + try { + TSocket socket = new TSocket("localhost",9160,10000); + socket.getSocket().setSoLinger(false, 0); + socket.getSocket().setKeepAlive(true); + socket.getSocket().setTcpNoDelay(true); + TTransport transport = new TFramedTransport(socket); + transport.open(); + client = new Cassandra.Client(new TBinaryProtocol(transport)); + } catch (SocketException e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } catch (TTransportException e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + // map + // (StorageProxy#read takes the commands and noodles hosts via #fetchRows) + // - then via StorageService#getLiveNaturalEndpoints + // - then via Table#getReplicationStrategy#getNaturalEndpoints + // RowPosition implements RingPosition + + return null; + } + + @Override + public void login(AuthenticationRequest auth_request) throws AuthenticationException, AuthorizationException, TException { + acquire().login(auth_request); + } + + @Override + public void set_keyspace(String keyspace) throws InvalidRequestException, TException { + acquire().set_keyspace(keyspace); + } + + @Override + public ColumnOrSuperColumn get(ByteBuffer key, ColumnPath column_path, ConsistencyLevel consistency_level) throws InvalidRequestException, NotFoundException, UnavailableException, TimedOutException, TException { + return acquire().get(key,column_path,consistency_level); + } + + @Override + public List get_slice(ByteBuffer key, ColumnParent column_parent, SlicePredicate predicate, ConsistencyLevel consistency_level) throws InvalidRequestException, UnavailableException, TimedOutException, TException { + return acquire().get_slice(key,column_parent,predicate,consistency_level); + } + + @Override + public int get_count(ByteBuffer key, ColumnParent column_parent, SlicePredicate predicate, ConsistencyLevel consistency_level) throws InvalidRequestException, UnavailableException, TimedOutException, TException { + return 0; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public Map> multiget_slice(List keys, ColumnParent column_parent, SlicePredicate predicate, ConsistencyLevel consistency_level) throws InvalidRequestException, UnavailableException, TimedOutException, TException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public Map multiget_count(List keys, ColumnParent column_parent, SlicePredicate predicate, ConsistencyLevel consistency_level) throws InvalidRequestException, UnavailableException, TimedOutException, TException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public List get_range_slices(ColumnParent column_parent, SlicePredicate predicate, KeyRange range, ConsistencyLevel consistency_level) throws InvalidRequestException, UnavailableException, TimedOutException, TException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public List get_indexed_slices(ColumnParent column_parent, IndexClause index_clause, SlicePredicate column_predicate, ConsistencyLevel consistency_level) throws InvalidRequestException, UnavailableException, TimedOutException, TException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void insert(ByteBuffer key, ColumnParent column_parent, Column column, ConsistencyLevel consistency_level) throws InvalidRequestException, UnavailableException, TimedOutException, TException { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void add(ByteBuffer key, ColumnParent column_parent, CounterColumn column, ConsistencyLevel consistency_level) throws InvalidRequestException, UnavailableException, TimedOutException, TException { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void remove(ByteBuffer key, ColumnPath column_path, long timestamp, ConsistencyLevel consistency_level) throws InvalidRequestException, UnavailableException, TimedOutException, TException { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void remove_counter(ByteBuffer key, ColumnPath path, ConsistencyLevel consistency_level) throws InvalidRequestException, UnavailableException, TimedOutException, TException { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void batch_mutate(Map>> mutation_map, ConsistencyLevel consistency_level) throws InvalidRequestException, UnavailableException, TimedOutException, TException { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void truncate(String cfname) throws InvalidRequestException, UnavailableException, TException { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public Map> describe_schema_versions() throws InvalidRequestException, TException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public List describe_keyspaces() throws InvalidRequestException, TException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String describe_cluster_name() throws TException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String describe_version() throws TException { + return "Hector-LCP-"+Constants.VERSION; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public List describe_ring(String keyspace) throws InvalidRequestException, TException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String describe_partitioner() throws TException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String describe_snitch() throws TException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public KsDef describe_keyspace(String keyspace) throws NotFoundException, InvalidRequestException, TException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public List describe_splits(String cfName, String start_token, String end_token, int keys_per_split) throws InvalidRequestException, TException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String system_add_column_family(CfDef cf_def) throws InvalidRequestException, SchemaDisagreementException, TException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String system_drop_column_family(String column_family) throws InvalidRequestException, SchemaDisagreementException, TException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String system_add_keyspace(KsDef ks_def) throws InvalidRequestException, SchemaDisagreementException, TException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String system_drop_keyspace(String keyspace) throws InvalidRequestException, SchemaDisagreementException, TException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String system_update_keyspace(KsDef ks_def) throws InvalidRequestException, SchemaDisagreementException, TException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String system_update_column_family(CfDef cf_def) throws InvalidRequestException, SchemaDisagreementException, TException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public CqlResult execute_cql_query(ByteBuffer query, Compression compression) throws InvalidRequestException, UnavailableException, TimedOutException, SchemaDisagreementException, TException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } +} diff --git a/lcp/src/test/java/me/prettyprint/lcp/LcpCassandraDaemonTest.java b/lcp/src/test/java/me/prettyprint/lcp/LcpCassandraDaemonTest.java new file mode 100644 index 000000000..963da562e --- /dev/null +++ b/lcp/src/test/java/me/prettyprint/lcp/LcpCassandraDaemonTest.java @@ -0,0 +1,34 @@ +package me.prettyprint.lcp; + +import me.prettyprint.hector.api.Cluster; +import me.prettyprint.hector.api.Keyspace; +import me.prettyprint.hector.api.factory.HFactory; +import org.apache.cassandra.thrift.Cassandra; +import org.apache.cassandra.thrift.Constants; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class LcpCassandraDaemonTest { + + private EmbeddedServerLauncher launcher = new EmbeddedServerLauncher(); + private Cluster cluster; + private Keyspace keyspace; + + @Before + public void localSetup() throws Exception { + launcher.setup(); + //cluster = HFactory.getOrCreateCluster("TestCluster","localhost:9170"); + + } + + @Test + public void testFireUp() throws Exception { + //assertEquals("19.20.0",cluster.describeThriftVersion()); + + Cassandra.Iface client = CassandraProxyClient.newProxyConnection("localhost",9170); + client.describe_version(); + } + +} \ No newline at end of file diff --git a/lcp/src/test/resources/cassandra.yaml b/lcp/src/test/resources/cassandra.yaml new file mode 100644 index 000000000..96a094c19 --- /dev/null +++ b/lcp/src/test/resources/cassandra.yaml @@ -0,0 +1,368 @@ +# Cassandra storage config YAML + +#NOTE !!!!!!!! NOTE +# See http://wiki.apache.org/cassandra/StorageConfiguration for +# full explanations of configuration directives +#NOTE !!!!!!!! NOTE + +# The name of the cluster. This is mainly used to prevent machines in +# one logical cluster from joining another. +cluster_name: 'Test Cluster' + +# You should always specify InitialToken when setting up a production +# cluster for the first time, and often when adding capacity later. +# The principle is that each node should be given an equal slice of +# the token ring; see http://wiki.apache.org/cassandra/Operations +# for more details. +# +# If blank, Cassandra will request a token bisecting the range of +# the heaviest-loaded existing node. If there is no load information +# available, such as is the case with a new cluster, it will pick +# a random token, which will lead to hot spots. +initial_token: + +# Set to true to make new [non-seed] nodes automatically migrate data +# to themselves from the pre-existing nodes in the cluster. Defaults +# to false because you can only bootstrap N machines at a time from +# an existing cluster of N, so if you are bringing up a cluster of +# 10 machines with 3 seeds you would have to do it in stages. Leaving +# this off for the initial start simplifies that. +auto_bootstrap: false + +# See http://wiki.apache.org/cassandra/HintedHandoff +hinted_handoff_enabled: true + +# authentication backend, implementing IAuthenticator; used to identify users +authenticator: org.apache.cassandra.auth.AllowAllAuthenticator + +# authorization backend, implementing IAuthority; used to limit access/provide permissions +authority: org.apache.cassandra.auth.AllowAllAuthority + +# any IPartitioner may be used, including your own as long as it is on +# the classpath. Out of the box, Cassandra provides +# org.apache.cassandra.dht.RandomPartitioner +# org.apache.cassandra.dht.ByteOrderedPartitioner, +# org.apache.cassandra.dht.OrderPreservingPartitioner, and +# org.apache.cassandra.dht.CollatingOrderPreservingPartitioner. +# (CollatingOPP colates according to EN,US rules, not naive byte +# ordering. Use this as an example if you need locale-aware collation.) +partitioner: org.apache.cassandra.dht.OrderPreservingPartitioner + +# directories where Cassandra should store data on disk. +data_file_directories: + - tmp/var/lib/cassandra/data + +# commit log +commitlog_directory: tmp/var/lib/cassandra/commitlog + +# saved caches +saved_caches_directory: tmp/var/lib/cassandra/saved_caches + + +# commitlog_sync may be either "periodic" or "batch." +# When in batch mode, Cassandra won't ack writes until the commit log +# has been fsynced to disk. It will wait up to +# CommitLogSyncBatchWindowInMS milliseconds for other writes, before +# performing the sync. +commitlog_sync: periodic + +# the other option is "timed," where writes may be acked immediately +# and the CommitLog is simply synced every commitlog_sync_period_in_ms +# milliseconds. +commitlog_sync_period_in_ms: 10000 + +# Addresses of hosts that are deemed contact points. +# Cassandra nodes use this list of hosts to find each other and learn +# the topology of the ring. You must change this if you are running +# multiple nodes! +seed_provider: + - class_name: org.apache.cassandra.locator.SimpleSeedProvider + parameters: + - seeds: "127.0.0.1" +# Access mode. mmapped i/o is substantially faster, but only practical on +# a 64bit machine (which notably does not include EC2 "small" instances) +# or relatively small datasets. "auto", the safe choice, will enable +# mmapping on a 64bit JVM. Other values are "mmap", "mmap_index_only" +# (which may allow you to get part of the benefits of mmap on a 32bit +# machine by mmapping only index files) and "standard". +# (The buffer size settings that follow only apply to standard, +# non-mmapped i/o.) +disk_access_mode: auto + +# Unlike most systems, in Cassandra writes are faster than reads, so +# you can afford more of those in parallel. A good rule of thumb is 2 +# concurrent reads per processor core. Increase ConcurrentWrites to +# the number of clients writing at once if you enable CommitLogSync + +# CommitLogSyncDelay. --> +concurrent_reads: 2 +concurrent_writes: 4 + +# This sets the amount of memtable flush writer threads. These will +# be blocked by disk io, and each one will hold a memtable in memory +# while blocked. If you have a large heap and many data directories, +# you can increase this value for better flush performance. +# By default this will be set to the amount of data directories defined. +#memtable_flush_writers: 1 + +# Buffer size to use when performing contiguous column slices. +# Increase this to the size of the column slices you typically perform +sliced_buffer_size_in_kb: 64 + +# TCP port, for commands and data +storage_port: 7001 + +# Address to bind to and tell other Cassandra nodes to connect to. You +# _must_ change this if you want multiple nodes to be able to +# communicate! +# +# Leaving it blank leaves it up to InetAddress.getLocalHost(). This +# will always do the Right Thing *if* the node is properly configured +# (hostname, name resolution, etc), and the Right Thing is to use the +# address associated with the hostname (it might not be). +# +# Setting this to 0.0.0.0 is always wrong. +listen_address: 127.0.0.1 + +# The address to bind the Thrift RPC service to -- clients connect +# here. Unlike ListenAddress above, you *can* specify 0.0.0.0 here if +# you want Thrift to listen on all interfaces. +# +# Leaving this blank has the same effect it does for ListenAddress, +# (i.e. it will be based on the configured hostname of the node). +rpc_address: localhost +# port for Thrift to listen for clients on +rpc_port: 9170 + +# enable or disable keepalive on rpc connections +rpc_keepalive: true + +# uncomment to set socket buffer sizes on rpc connections +# rpc_send_buff_size_in_bytes: +# rpc_recv_buff_size_in_bytes: + +# Frame size for thrift (maximum field length). +# 0 disables TFramedTransport in favor of TSocket. This option +# is deprecated; we strongly recommend using Framed mode. +thrift_framed_transport_size_in_mb: 15 + +# The max length of a thrift message, including all fields and +# internal thrift overhead. +thrift_max_message_length_in_mb: 16 + +# Whether or not to take a snapshot before each compaction. Be +# careful using this option, since Cassandra won't clean up the +# snapshots for you. Mostly useful if you're paranoid when there +# is a data format change. +snapshot_before_compaction: false + +# change this to increase the compaction thread's priority. In java, 1 is the +# lowest priority and that is our default. +# compaction_thread_priority: 1 + +# Add column indexes to a row after its contents reach this size. +# Increase if your column values are large, or if you have a very large +# number of columns. The competing causes are, Cassandra has to +# deserialize this much of the row to read a single column, so you want +# it to be small - at least if you do many partial-row reads - but all +# the index data is read for each access, so you don't want to generate +# that wastefully either. +column_index_size_in_kb: 64 + +# Size limit for rows being compacted in memory. Larger rows will spill +# over to disk and use a slower two-pass compaction process. A message +# will be logged specifying the row key. +in_memory_compaction_limit_in_mb: 16 + +# Time to wait for a reply from other nodes before failing the command +rpc_timeout_in_ms: 10000 + +# phi value that must be reached for a host to be marked down. +# most users should never need to adjust this. +# phi_convict_threshold: 8 + +# endpoint_snitch -- Set this to a class that implements +# IEndpointSnitch, which will let Cassandra know enough +# about your network topology to route requests efficiently. +# Out of the box, Cassandra provides +# - org.apache.cassandra.locator.SimpleSnitch: +# Treats Strategy order as proximity. This improves cache locality +# when disabling read repair, which can further improve throughput. +# - org.apache.cassandra.locator.RackInferringSnitch: +# Proximity is determined by rack and data center, which are +# assumed to correspond to the 3rd and 2nd octet of each node's +# IP address, respectively +# org.apache.cassandra.locator.PropertyFileSnitch: +# - Proximity is determined by rack and data center, which are +# explicitly configured in cassandra-rack.properties. +endpoint_snitch: org.apache.cassandra.locator.SimpleSnitch + +# dynamic_snitch -- This boolean controls whether the above snitch is +# wrapped with a dynamic snitch, which will monitor read latencies +# and avoid reading from hosts that have slowed (due to compaction, +# for instance) +dynamic_snitch: true +# controls how often to perform the more expensive part of host score +# calculation +dynamic_snitch_update_interval_in_ms: 100 +# controls how often to reset all host scores, allowing a bad host to +# possibly recover +dynamic_snitch_reset_interval_in_ms: 600000 +# if set greater than zero and read_repair_chance is < 1.0, this will allow +# 'pinning' of replicas to hosts in order to increase cache capacity. +# The badness threshold will control how much worse the pinned host has to be +# before the dynamic snitch will prefer other replicas over it. This is +# expressed as a double which represents a percentage. +dynamic_snitch_badness_threshold: 0.0 + +# request_scheduler -- Set this to a class that implements +# RequestScheduler, which will schedule incoming client requests +# according to the specific policy. This is useful for multi-tenancy +# with a single Cassandra cluster. +# NOTE: This is specifically for requests from the client and does +# not affect inter node communication. +# org.apache.cassandra.scheduler.NoScheduler - No scheduling takes place +# org.apache.cassandra.scheduler.RoundRobinScheduler - Round robin of +# client requests to a node with a separate queue for each +# request_scheduler_id. The scheduler is further customized by +# request_scheduler_options as described below. +request_scheduler: org.apache.cassandra.scheduler.NoScheduler + +encryption_options: + internode_encryption: none + keystore: conf/.keystore + keystore_password: cassandra + truststore: conf/.truststore + truststore_password: cassandra +# Scheduler Options vary based on the type of scheduler +# NoScheduler - Has no options +# RoundRobin +# - throttle_limit -- The throttle_limit is the number of in-flight +# requests per client. Requests beyond +# that limit are queued up until +# running requests can complete. +# The value of 80 here is twice the number of +# concurrent_reads + concurrent_writes. +# - default_weight -- default_weight is optional and allows for +# overriding the default which is 1. +# - weights -- Weights are optional and will default to 1 or the +# overridden default_weight. The weight translates into how +# many requests are handled during each turn of the +# RoundRobin, based on the scheduler id. +# +# request_scheduler_options: +# throttle_limit: 80 +# default_weight: 5 +# weights: +# Keyspace1: 1 +# Keyspace2: 5 + +# request_scheduler_id -- An identifer based on which to perform +# the request scheduling. Currently the only valid option is keyspace. +# request_scheduler_id: keyspace + +# The Index Interval determines how large the sampling of row keys +# is for a given SSTable. The larger the sampling, the more effective +# the index is at the cost of space. +index_interval: 128 + +# A ColumnFamily is the Cassandra concept closest to a relational table. +# +# Keyspaces are separate groups of ColumnFamilies. Except in very +# unusual circumstances you will have one Keyspace per application. +# +# Keyspace required parameters: +# - name: name of the keyspace; "system" and "definitions" are +# reserved for Cassandra Internals. +# - replica_placement_strategy: the class that determines how replicas +# are distributed among nodes. Contains both the class as well as +# configuration information. Must extend AbstractReplicationStrategy. +# Out of the box, Cassandra provides +# * org.apache.cassandra.locator.SimpleStrategy +# * org.apache.cassandra.locator.NetworkTopologyStrategy +# * org.apache.cassandra.locator.OldNetworkTopologyStrategy +# +# SimpleStrategy merely places the first +# replica at the node whose token is closest to the key (as determined +# by the Partitioner), and additional replicas on subsequent nodes +# along the ring in increasing Token order. +# +# With NetworkTopologyStrategy, +# for each datacenter, you can specify how many replicas you want +# on a per-keyspace basis. Replicas are placed on different racks +# within each DC, if possible. This strategy also requires rack aware +# snitch, such as RackInferringSnitch or PropertyFileSnitch. +# An example: +# - name: Keyspace1 +# replica_placement_strategy: org.apache.cassandra.locator.NetworkTopologyStrategy +# strategy_options: +# DC1 : 3 +# DC2 : 2 +# DC3 : 1 +# +# OldNetworkToplogyStrategy [formerly RackAwareStrategy] +# places one replica in each of two datacenters, and the third on a +# different rack in in the first. Additional datacenters are not +# guaranteed to get a replica. Additional replicas after three are placed +# in ring order after the third without regard to rack or datacenter. +# +# - replication_factor: Number of replicas of each row +# - column_families: column families associated with this keyspace +# +# ColumnFamily required parameters: +# - name: name of the ColumnFamily. Must not contain the character "-". +# - compare_with: tells Cassandra how to sort the columns for slicing +# operations. The default is BytesType, which is a straightforward +# lexical comparison of the bytes in each column. Other options are +# AsciiType, UTF8Type, LexicalUUIDType, TimeUUIDType, LongType, +# and IntegerType (a generic variable-length integer type). +# You can also specify the fully-qualified class name to a class of +# your choice extending org.apache.cassandra.db.marshal.AbstractType. +# +# ColumnFamily optional parameters: +# - keys_cached: specifies the number of keys per sstable whose +# locations we keep in memory in "mostly LRU" order. (JUST the key +# locations, NOT any column values.) Specify a fraction (value less +# than 1) or an absolute number of keys to cache. Defaults to 200000 +# keys. +# - rows_cached: specifies the number of rows whose entire contents we +# cache in memory. Do not use this on ColumnFamilies with large rows, +# or ColumnFamilies with high write:read ratios. Specify a fraction +# (value less than 1) or an absolute number of rows to cache. +# Defaults to 0. (i.e. row caching is off by default) +# - comment: used to attach additional human-readable information about +# the column family to its definition. +# - read_repair_chance: specifies the probability with which read +# repairs should be invoked on non-quorum reads. must be between 0 +# and 1. defaults to 1.0 (always read repair). +# - gc_grace_seconds: specifies the time to wait before garbage +# collecting tombstones (deletion markers). defaults to 864000 (10 +# days). See http://wiki.apache.org/cassandra/DistributedDeletes +# - default_validation_class: specifies a validator class to use for +# validating all the column values in the CF. +# - min_compaction_threshold: the minimum number of SSTables needed +# to start a minor compaction. increasing this will cause minor +# compactions to start less frequently and be more intensive. setting +# this to 0 disables minor compactions. defaults to 4. +# - max_compaction_threshold: the maximum number of SSTables allowed +# before a minor compaction is forced. decreasing this will cause +# minor compactions to start more frequently and be less intensive. +# setting this to 0 disables minor compactions. defaults to 32. +# - row_cache_save_period_in_seconds: number of seconds between saving +# row caches. The row caches can be saved periodically and if one +# exists on startup it will be loaded. +# - key_cache_save_period_in_seconds: number of seconds between saving +# key caches. The key caches can be saved periodically and if one +# exists on startup it will be loaded. +# - memtable_flush_after_mins: The maximum time to leave a dirty table +# unflushed. This should be large enough that it won't cause a flush +# storm of all memtables during periods of inactivity. +# - memtable_throughput_in_mb: The maximum size of the memtable before +# it is flushed. If undefined, 1/8 * heapsize will be used. +# - memtable_operations_in_millions: Number of operations in millions +# before the memtable is flushed. If undefined, throughput / 64 * 0.3 +# will be used. +# +# NOTE: this keyspace definition is for demonstration purposes only. +# Cassandra will not load these definitions during startup. See +# http://wiki.apache.org/cassandra/FAQ#no_keyspaces for an explanation. + diff --git a/lcp/src/test/resources/log4j-server.properties b/lcp/src/test/resources/log4j-server.properties new file mode 100644 index 000000000..15b4e5c10 --- /dev/null +++ b/lcp/src/test/resources/log4j-server.properties @@ -0,0 +1,35 @@ +# 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. + +# for production, you should probably set the root to INFO +# and the pattern to %c instead of %l. (%l is slower.) + +# output messages into a rolling log file as well as stdout +log4j.rootLogger=INFO,stdout + +# stdout +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%-5p [%t]: %m%n +log4j.appender.stdout.follow=true + +# Application logging options +#log4j.logger.org.apache.cassandra=DEBUG +#log4j.logger.org.apache.cassandra.db=DEBUG +#log4j.logger.org.apache.cassandra.service.StorageProxy=DEBUG + +# Adding this to avoid thrift logging disconnect errors. +log4j.logger.org.apache.thrift.server.TNonblockingServer=ERROR \ No newline at end of file diff --git a/pom.xml b/pom.xml index 9123f36d5..dfc0d2871 100644 --- a/pom.xml +++ b/pom.xml @@ -82,6 +82,7 @@ core object-mapper test + lcp