(10);
96 | avoidNodes.add(conn.getNode().getAddress());
97 |
98 | retries++;
99 | lastException = e;
100 | } else if (e instanceof NotFoundException) {
101 | // Re-throw application-level exceptions immediately.
102 | throw operandPolicy.getExceptionTranslator().translate(e);
103 | } else {
104 | // This connection is "broken" by network timeout or other problem.
105 | conn.corrupted();
106 |
107 | // Re-throw application-level exceptions immediately.
108 | throw operandPolicy.getExceptionTranslator().translate(e);
109 | }
110 | } finally {
111 | conn.release();
112 | }
113 | } while (retries < operandPolicy.getMaxOpRetries());
114 |
115 | throw operandPolicy.getExceptionTranslator().translate(lastException);
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/OperandPolicy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops;
26 |
27 | import org.scale7.cassandra.pelops.exceptions.IExceptionTranslator;
28 |
29 | /**
30 | * General policy configuration.
31 | */
32 | public class OperandPolicy {
33 | int maxOpRetries = 3;
34 | boolean deleteIfNull = false;
35 | IExceptionTranslator exceptionTranslator = new IExceptionTranslator.ExceptionTranslator();
36 |
37 | public OperandPolicy() {
38 | }
39 |
40 | public OperandPolicy(int maxOpRetries, boolean deleteIfNull) {
41 | this.maxOpRetries = maxOpRetries;
42 | this.deleteIfNull = deleteIfNull;
43 | }
44 |
45 | public OperandPolicy(int maxOpRetries, boolean deleteIfNull, IExceptionTranslator exceptionTranslator) {
46 | this.maxOpRetries = maxOpRetries;
47 | this.deleteIfNull = deleteIfNull;
48 | this.exceptionTranslator = exceptionTranslator;
49 | }
50 |
51 | public int getMaxOpRetries() {
52 | return maxOpRetries;
53 | }
54 |
55 | /**
56 | * Max number of times to retry an operation before giving up.
57 | * Default to 2.
58 | * @param maxOpRetries the value
59 | */
60 | public OperandPolicy setMaxOpRetries(int maxOpRetries) {
61 | this.maxOpRetries = maxOpRetries;
62 | return this;
63 | }
64 |
65 | /**
66 | * Dictates if pelops should issue deletes when it detects null values being written in a mutation batch.
67 | * @return true if deletes should be issued by default
68 | */
69 | public boolean isDeleteIfNull() {
70 | return deleteIfNull;
71 | }
72 |
73 | /**
74 | * Dictates if pelops should issue deletes when it detects null values being written in a mutation batch.
75 | * @param deleteIfNull true if deletes should be issued by default
76 | */
77 | public OperandPolicy setDeleteIfNull(boolean deleteIfNull) {
78 | this.deleteIfNull = deleteIfNull;
79 | return this;
80 | }
81 |
82 | /**
83 | * The translater used to convert checked Thirft/Cassandra exceptions into unchecked PelopsExceptions.
84 | * @return the translator
85 | */
86 | public IExceptionTranslator getExceptionTranslator() {
87 | return exceptionTranslator;
88 | }
89 |
90 | /**
91 | * The translater used to convert checked Thirft/Cassandra exceptions into unchecked PelopsExceptions.
92 | * Note: by default {@link org.scale7.cassandra.pelops.exceptions.IExceptionTranslator.ExceptionTranslator} is used.
93 | * @param exceptionTranslator the translator
94 | */
95 | public OperandPolicy setExceptionTranslator(IExceptionTranslator exceptionTranslator) {
96 | this.exceptionTranslator = exceptionTranslator;
97 | return this;
98 | }
99 |
100 | /**
101 | * Returns a shallow copy of this object.
102 | * @return a copy of this
103 | */
104 | public OperandPolicy copy() {
105 | return new OperandPolicy(this.getMaxOpRetries(), this.isDeleteIfNull(), getExceptionTranslator());
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/PageOfIterator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops;
26 |
27 | import java.util.Iterator;
28 | import java.util.List;
29 | import java.util.NoSuchElementException;
30 |
31 | import org.apache.cassandra.thrift.ConsistencyLevel;
32 |
33 | public abstract class PageOfIterator implements Iterator {
34 | protected final Selector selector;
35 | protected final String columnFamily;
36 | protected final Bytes rowKey;
37 | protected final boolean reversed;
38 | protected final int batchSize;
39 | protected final ConsistencyLevel cLevel;
40 | protected Bytes startBeyondName;
41 | private boolean isMoreToFetch = false;
42 | private Iterator currentBatchIterator;
43 |
44 | public PageOfIterator(final Selector selector, final String columnFamily, final Bytes rowKey,
45 | final Bytes startBeyondName, final boolean reversed, final int batchSize,
46 | final ConsistencyLevel cLevel) {
47 | this.batchSize = batchSize;
48 | this.rowKey = rowKey;
49 | this.cLevel = cLevel;
50 | this.reversed = reversed;
51 | this.columnFamily = columnFamily;
52 | this.startBeyondName = startBeyondName;
53 | this.selector = selector;
54 | }
55 |
56 | private void fetchNextBatchInternal() {
57 | List batch = fetchNextBatch();
58 | currentBatchIterator = batch.iterator();
59 | startBeyondName = nextStartBeyondName(batch);
60 | isMoreToFetch = batch.size() == this.batchSize;
61 | }
62 |
63 | protected abstract List fetchNextBatch();
64 |
65 | protected abstract Bytes nextStartBeyondName(List batch);
66 |
67 | /**
68 | * Returns true if the iteration has more super columns. (In other words, returns true if next would return a super column rather than throwing an exception.)
69 | */
70 | @Override
71 | public boolean hasNext() {
72 | if (currentBatchIterator == null)
73 | fetchNextBatchInternal();
74 |
75 | boolean isMoreInBatch = currentBatchIterator.hasNext();
76 |
77 | if (!isMoreInBatch && isMoreToFetch) {
78 | fetchNextBatchInternal();
79 | return hasNext();
80 | }
81 |
82 | return isMoreInBatch;
83 | }
84 |
85 | /**
86 | * Returns the next super column in the iteration.
87 | * @return the next super column
88 | * @throws java.util.NoSuchElementException iteration has no more super columns.
89 | */
90 | @Override
91 | public E next() {
92 | if (currentBatchIterator == null)
93 | fetchNextBatchInternal();
94 |
95 | E column = null;
96 | try {
97 | column = currentBatchIterator.next();
98 | } catch (NoSuchElementException e) {
99 | if (isMoreToFetch) {
100 | fetchNextBatchInternal();
101 | return next();
102 | }
103 |
104 | throw e;
105 | }
106 |
107 | return column;
108 | }
109 |
110 | /**
111 | * Not supported.
112 | */
113 | @Override
114 | public void remove() {
115 | throw new UnsupportedOperationException();
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/Pelops.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops;
26 |
27 | import java.util.concurrent.ConcurrentHashMap;
28 |
29 | import org.scale7.cassandra.pelops.pool.CommonsBackedPool;
30 | import org.scale7.cassandra.pelops.pool.IThriftPool;
31 | import org.scale7.portability.SystemProxy;
32 | import org.slf4j.Logger;
33 |
34 | public class Pelops {
35 |
36 | private static final Logger logger = SystemProxy.getLoggerFromFactory(Pelops.class);
37 |
38 | private static ConcurrentHashMap poolMap = new ConcurrentHashMap();
39 |
40 | /**
41 | * Add a new Thrift connection pool for a specific cluster and keyspace. The name given to the pool is later used
42 | * when creating operands such as Mutator
and Selector
.
43 | * @param poolName A name used to reference the pool e.g. "MainDatabase" or "LucandraIndexes"
44 | * @param cluster The Cassandra cluster that network connections will be made to
45 | * @param keyspace The keyspace in the Cassandra cluster against which pool operations will apply
46 | */
47 | public static void addPool(String poolName, Cluster cluster, String keyspace) {
48 | IThriftPool pool = new CommonsBackedPool(cluster, keyspace);
49 | addPool(poolName, pool);
50 | }
51 |
52 | /**
53 | * Add a new Thrift connection pool for a specific cluster and keyspace. The name given to the pool is later used
54 | * when creating operands such as Mutator
and Selector
.
55 | * @param poolName A name used to reference the pool e.g. "MainDatabase" or "LucandraIndexes"
56 | * @param cluster The Cassandra cluster that network connections will be made to
57 | * @param keyspace The keyspace in the Cassandra cluster against which pool operations will apply
58 | * @param policy The configuration used by the pool
59 | * @param operandPolicy The configuration used by the {@link org.scale7.cassandra.pelops.Operand}
60 | */
61 | public static void addPool(String poolName, Cluster cluster, String keyspace, CommonsBackedPool.Policy policy, OperandPolicy operandPolicy) {
62 | IThriftPool pool = new CommonsBackedPool(cluster, keyspace, policy, operandPolicy);
63 | addPool(poolName, pool);
64 | }
65 |
66 | /**
67 | * Add an already instantiated instance of {@link IThriftPool} to pelops.
68 | * @param poolName A name used to reference the pool e.g. "MainDatabase" or "LucandraIndexes"
69 | * @param thriftPool an instance of the {@link IThriftPool} interface
70 | */
71 | public static void addPool(String poolName, IThriftPool thriftPool) {
72 | logger.info("Pelops adds new pool {}", poolName);
73 | poolMap.put(poolName, thriftPool);
74 | }
75 |
76 | /**
77 | * Removes and shuts down a previously added Thrift connection pool.
78 | *
79 | * @param poolName A name used to reference the pool e.g. "MainDatabase" or "LucandraIndexes"
80 | */
81 | public static void removePool(String poolName) {
82 | logger.info("Pelops removes pool {}", poolName);
83 | IThriftPool pool = poolMap.remove(poolName);
84 | if (pool != null) // avoid null pointers
85 | pool.shutdown();
86 | }
87 |
88 | /**
89 | * Shutdown Pelops. This proceeds by shutting down all connection pools.
90 | */
91 | public static void shutdown() {
92 | logger.info("Pelops starting to shutdown...");
93 | for (IThriftPool pool : poolMap.values())
94 | pool.shutdown();
95 | logger.info("Pelops has shutdown");
96 | }
97 |
98 | /**
99 | * Create a Selector
object.
100 | * @param poolName The name of the connection pool to use (this determines the Cassandra database cluster)
101 | * @return A new Selector
object
102 | */
103 | public static Selector createSelector(String poolName) {
104 | return poolMap.get(poolName).createSelector();
105 | }
106 |
107 | /**
108 | * Create a Mutator
object using the current time as the operation time stamp. The Mutator
object
109 | * must only be used to execute 1 mutation operation.
110 | * @param poolName The name of the connection pool to use (this determines the Cassandra database cluster)
111 | * @return A new Mutator
object
112 | */
113 | public static Mutator createMutator(String poolName) {
114 | return poolMap.get(poolName).createMutator();
115 | }
116 |
117 | /**
118 | * Create a Mutator
object with an arbitrary time stamp. The Mutator
object
119 | * must only be used to execute 1 mutation operation.
120 | * @param poolName The name of the connection pool to use (this determines the Cassandra database cluster)
121 | * @param timestamp The default time stamp to use for operations
122 | * @return A new Mutator
object
123 | */
124 | public static Mutator createMutator(String poolName, long timestamp) {
125 | return poolMap.get(poolName).createMutator(timestamp);
126 | }
127 |
128 | /**
129 | * Create a Mutator
object with an arbitrary time stamp. The Mutator
object
130 | * must only be used to execute 1 mutation operation.
131 | * @param poolName The name of the connection pool to use (this determines the Cassandra database cluster)
132 | * @param timestamp The default time stamp to use for operations
133 | * @param deleteIfNull If true the mutator will default to issuing deletes when it detects null values on a column
134 | * passed to the various write methods.
135 | * @return A new Mutator
object
136 | */
137 | public static Mutator createMutator(String poolName, long timestamp, boolean deleteIfNull) {
138 | return poolMap.get(poolName).createMutator(timestamp, deleteIfNull);
139 | }
140 |
141 | /**
142 | * Create a {@link RowDeletor row deletor} object using the current time as the operation time stamp.
143 | * @param poolName The name of the connection pool to use (this determines the Cassandra database cluster)
144 | * @return A new {@link RowDeletor row deletor} object
145 | */
146 | public static RowDeletor createRowDeletor(String poolName) {
147 | return poolMap.get(poolName).createRowDeletor();
148 | }
149 |
150 | /**
151 | * Create a {@link RowDeletor row deletor} object with an arbitrary time stamp.
152 | * @param poolName The name of the connection pool to use (this determines the Cassandra database cluster)
153 | * @param timestamp The default time stamp to use for operations
154 | * @return A new {@link RowDeletor row deletor} object
155 | */
156 | public static RowDeletor createRowDeletor(String poolName, long timestamp) {
157 | return poolMap.get(poolName).createRowDeletor(timestamp);
158 | }
159 |
160 | /**
161 | * Create a ClusterManager
object for use managing the cluster. For example, querying
162 | * the version of the Cassandra software, or the cluster name.
163 | * @param cluster
164 | * @return
165 | */
166 | public static ClusterManager createClusterManager(Cluster cluster) {
167 | return new ClusterManager(cluster);
168 | }
169 |
170 | /**
171 | * Create a KeyspaceManager
object for use managing keyspaces in the cluster. For example,
172 | * querying the list of keyspaces, or adding a new keyspace.
173 | * @param cluster
174 | * @return
175 | */
176 | public static KeyspaceManager createKeyspaceManager(Cluster cluster) {
177 | return new KeyspaceManager(cluster);
178 | }
179 |
180 | /**
181 | * Create a ColumnFamilyManager
object for use managing column families inside a keyspace. For
182 | * example, adding or removing a column family.
183 | * @param cluster
184 | * @param keyspace
185 | * @return
186 | */
187 | public static ColumnFamilyManager createColumnFamilyManager(Cluster cluster, String keyspace) {
188 | return new ColumnFamilyManager(cluster, keyspace);
189 | }
190 |
191 | /**
192 | * Get a direct reference to a DbConnPool. This should never be needed while using Pelops's Mutator
and
193 | * Selector
in normal usage. The reason this function is provided, is so that the Pelops connection pooling system can be
194 | * used in conjunction with other systems such as Lucandra.
195 | * @param poolName The name of the pool
196 | * @return A direct reference to the specified pool
197 | */
198 | public static IThriftPool getDbConnPool(String poolName) {
199 | return poolMap.get(poolName);
200 | }
201 | }
202 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/RowDeletor.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops;
26 |
27 | import static org.scale7.cassandra.pelops.Bytes.fromUTF8;
28 | import static org.scale7.cassandra.pelops.Bytes.nullSafeGet;
29 |
30 | import org.apache.cassandra.thrift.ColumnPath;
31 | import org.apache.cassandra.thrift.ConsistencyLevel;
32 | import org.scale7.cassandra.pelops.exceptions.PelopsException;
33 | import org.scale7.cassandra.pelops.pool.IThriftPool;
34 | import org.scale7.cassandra.pelops.pool.IThriftPool.IPooledConnection;
35 |
36 | /**
37 | * Facilitates the removal of data at a key-level.
38 | *
39 | * @author dominicwilliams
40 | *
41 | */
42 | public class RowDeletor extends Operand {
43 |
44 | private final long timestamp;
45 |
46 | /**
47 | * Delete a row with a specified key from a specified column family. The function succeeds even if
48 | * the row does not exist.
49 | * @param columnFamily The column family from which to delete the row
50 | * @param rowKey The key of the row
51 | * @param cLevel The Cassandra consistency level to be used
52 | * @throws PelopsException
53 | */
54 | public void deleteRow(final String columnFamily, final String rowKey, final ConsistencyLevel cLevel) throws PelopsException {
55 | deleteRow(columnFamily, fromUTF8(rowKey), cLevel);
56 | }
57 |
58 | /**
59 | * Delete a row with a specified key from a specified column family. The function succeeds even if
60 | * the row does not exist.
61 | * @param columnFamily The column family from which to delete the row
62 | * @param rowKey The key of the row
63 | * @param cLevel The Cassandra consistency level to be used
64 | * @throws PelopsException
65 | */
66 | public void deleteRow(String columnFamily, final Bytes rowKey, final ConsistencyLevel cLevel) throws PelopsException {
67 | final ColumnPath path = new ColumnPath(columnFamily);
68 | IOperation operation = new IOperation() {
69 | @Override
70 | public Void execute(IPooledConnection conn) throws Exception {
71 | conn.getAPI().remove(nullSafeGet(rowKey), path, timestamp, cLevel);
72 | return null;
73 | }
74 | };
75 | tryOperation(operation);
76 | }
77 |
78 | public RowDeletor(IThriftPool thrift) {
79 | this(thrift, System.currentTimeMillis() * 1000);
80 | }
81 |
82 | public RowDeletor(IThriftPool thrift, long timestamp) {
83 | super(thrift);
84 | this.timestamp = timestamp;
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/RowIterator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops;
26 |
27 | import java.util.Iterator;
28 | import java.util.LinkedHashMap;
29 | import java.util.List;
30 | import java.util.Map;
31 | import java.util.NoSuchElementException;
32 |
33 | import org.apache.cassandra.thrift.ConsistencyLevel;
34 | import org.apache.cassandra.thrift.SlicePredicate;
35 |
36 | public abstract class RowIterator implements Iterator>> {
37 | protected final Selector selector;
38 | protected final String columnFamily;
39 | protected Bytes startBeyondKey;
40 | protected final int batchSize;
41 | protected final SlicePredicate colPredicate;
42 | protected final ConsistencyLevel cLevel;
43 |
44 | private boolean isFirstBatch = true;
45 | private boolean isMoreToFetch = false;
46 | private Iterator>> currentBatchIterator;
47 |
48 | protected RowIterator(Selector selector, String columnFamily, Bytes startBeyondKey, int batchSize, SlicePredicate colPredicate, ConsistencyLevel cLevel) {
49 | this.selector = selector;
50 | this.columnFamily = columnFamily;
51 | this.startBeyondKey = startBeyondKey;
52 | this.batchSize = batchSize;
53 | this.colPredicate = colPredicate;
54 | this.cLevel = cLevel;
55 | }
56 |
57 | private void fetchNextBatchInternal() {
58 | LinkedHashMap> batch = fetchNextBatch();
59 | isMoreToFetch = batch.size() == this.batchSize;
60 |
61 | if (isFirstBatch) {
62 | isFirstBatch = false;
63 | } else {
64 | // we need to remove the first entry in the batch to avoid feeding through the iterator twice...
65 | batch.remove(this.startBeyondKey);
66 | }
67 |
68 | currentBatchIterator = batch.entrySet().iterator();
69 |
70 | }
71 |
72 | protected abstract LinkedHashMap> fetchNextBatch();
73 |
74 | @Override
75 | public boolean hasNext() {
76 | if (currentBatchIterator == null)
77 | fetchNextBatchInternal();
78 |
79 | boolean isMoreInBatch = currentBatchIterator.hasNext();
80 |
81 | if (!isMoreInBatch && isMoreToFetch) {
82 | fetchNextBatchInternal();
83 | return hasNext();
84 | }
85 |
86 | return isMoreInBatch;
87 | }
88 |
89 | @Override
90 | public Map.Entry> next() {
91 | if (currentBatchIterator == null)
92 | fetchNextBatchInternal();
93 |
94 | Map.Entry> row = null;
95 | try {
96 | row = currentBatchIterator.next();
97 |
98 | if (row != null) {
99 | startBeyondKey = row.getKey();
100 | }
101 | } catch (NoSuchElementException e) {
102 | if (isMoreToFetch) {
103 | fetchNextBatchInternal();
104 | return next();
105 | }
106 |
107 | throw e;
108 | }
109 |
110 | return row;
111 | }
112 |
113 | @Override
114 | public void remove() {
115 | throw new UnsupportedOperationException();
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/SimpleConnectionAuthenticator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops;
26 |
27 | import java.util.HashMap;
28 | import java.util.Map;
29 |
30 | import org.apache.cassandra.thrift.AuthenticationRequest;
31 |
32 | public class SimpleConnectionAuthenticator implements IConnectionAuthenticator {
33 | public static final java.lang.String USERNAME_KEY = "username";
34 | public static final java.lang.String PASSWORD_KEY = "password";
35 |
36 | private String username;
37 | private String password;
38 |
39 | public SimpleConnectionAuthenticator() {
40 |
41 | }
42 |
43 | public SimpleConnectionAuthenticator(String username,String password) {
44 | this.username = username;
45 | this.password = password;
46 | }
47 |
48 | @Override
49 | public AuthenticationRequest getAuthenticationRequest() {
50 | Map params = new HashMap();
51 | params.put(USERNAME_KEY, username);
52 | params.put(PASSWORD_KEY, password);
53 | return new AuthenticationRequest(params);
54 | }
55 |
56 | @Override
57 | public String toString() {
58 | return "SimpleConnectionAuthenticator [username=" + username
59 | + ", password=" + password + "]";
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/SuperColumnIterator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops;
26 |
27 | import java.util.List;
28 |
29 | import org.apache.cassandra.thrift.ConsistencyLevel;
30 | import org.apache.cassandra.thrift.SuperColumn;
31 |
32 | /**
33 | * Encapsulates the logic required to iterate over super columns. See
34 | * {@link org.scale7.cassandra.pelops.Selector#iterateSuperColumnsFromRow(String, Bytes, Bytes, boolean, int, org.apache.cassandra.thrift.ConsistencyLevel)}
35 | * for more detail.
36 | */
37 | public class SuperColumnIterator extends PageOfIterator {
38 | public SuperColumnIterator(final Selector selector, final String columnFamily, final Bytes rowKey,
39 | final Bytes startBeyondName, final boolean reversed, final int batchSize,
40 | final ConsistencyLevel cLevel) {
41 | super(selector, columnFamily, rowKey, startBeyondName, reversed, batchSize, cLevel);
42 | }
43 |
44 | protected List fetchNextBatch() {
45 | return this.selector.getPageOfSuperColumnsFromRow(
46 | this.columnFamily, this.rowKey, this.startBeyondName, this.reversed, this.batchSize, this.cLevel
47 | );
48 | }
49 |
50 | @Override
51 | protected Bytes nextStartBeyondName(List batch) {
52 | return batch.isEmpty() ? null : Bytes.fromByteArray(batch.get(batch.size() - 1).getName());
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/UuidHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops;
26 |
27 | import java.util.Calendar;
28 | import java.util.Date;
29 | import java.util.UUID;
30 |
31 | import org.joda.time.DateTime;
32 |
33 | public class UuidHelper {
34 | /*
35 | Magic number obtained from #cassandra's thobbs, who
36 | claims to have stolen it from a Python library.
37 | */
38 | static final long NUM_100NS_INTERVALS_SINCE_UUID_EPOCH = 0x01b21dd213814000L;
39 |
40 | /**
41 | * Generate a new time UUID insatnce.
42 | * @return A new time UUID object
43 | */
44 | public static java.util.UUID newTimeUuid() {
45 | return java.util.UUID.fromString(new com.eaio.uuid.UUID().toString());
46 | }
47 |
48 | /**
49 | * @see #nonUniqueTimeUuidForDate(long)
50 | */
51 | public static java.util.UUID nonUniqueTimeUuidForDate(Date d) {
52 | return nonUniqueTimeUuidForDate(d.getTime());
53 | }
54 |
55 | /**
56 | * @see #nonUniqueTimeUuidForDate(long)
57 | */
58 | public static java.util.UUID nonUniqueTimeUuidForDate(Calendar c) {
59 | return nonUniqueTimeUuidForDate(c.getTime());
60 | }
61 |
62 | /**
63 | * @see #nonUniqueTimeUuidForDate(long)
64 | * Note: the use of the class required the *optional* joda-time dependency.
65 | */
66 | public static java.util.UUID nonUniqueTimeUuidForDate(DateTime d) {
67 | return nonUniqueTimeUuidForDate(d.getMillis());
68 | }
69 |
70 | /**
71 | * This method is useful to create a *non-unique* TimeUUID instance from some time other than the present.
72 | * For example, to use as the lower bound in a SlicePredicate to retrieve all columns whose TimeUUID comes
73 | * after time X.
74 | *
75 | *
WARNING: Never assume such a UUID is unique, use it only as a marker for a specific time.
76 | *
Note: This method and it's doco is taken (almost verbatim) from the Cassandra WIKI
77 | * (http://wiki.apache.org/cassandra/FAQ#working_with_timeuuid_in_java).
78 | * @param millis Gets the milliseconds of the datetime instant from the Java epoch of 1970-01-01T00:00:00Z
79 | * @return return
80 | */
81 | public static java.util.UUID nonUniqueTimeUuidForDate(long millis) {
82 | long time = millis * 10000 + NUM_100NS_INTERVALS_SINCE_UUID_EPOCH;
83 | long timeLow = time & 0xffffffffL;
84 | long timeMid = time & 0xffff00000000L;
85 | long timeHi = time & 0xfff000000000000L;
86 | long upperLong = (timeLow << 32) | (timeMid >> 16) | (1 << 12) | (timeHi >> 48) ;
87 | return new java.util.UUID(upperLong, 0xC000000000000000L);
88 | }
89 |
90 | /**
91 | *
Extracts the millis from the Java epoch of 1970-01-01T00:00:00Z.
92 | * @param uuid the time uuid
93 | * @return the millis since Java epoch
94 | */
95 | public static long millisFromTimeUuid(UUID uuid) {
96 | return (uuid.timestamp() - NUM_100NS_INTERVALS_SINCE_UUID_EPOCH) / 10000;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/Validation.java:
--------------------------------------------------------------------------------
1 | package org.scale7.cassandra.pelops;
2 |
3 | import java.nio.ByteBuffer;
4 | import java.util.List;
5 |
6 | import org.apache.cassandra.thrift.Column;
7 | import org.apache.cassandra.thrift.CounterColumn;
8 | import org.scale7.cassandra.pelops.exceptions.ModelException;
9 |
10 | public class Validation {
11 |
12 | public static ByteBuffer safeGetRowKey(Bytes rowKey) {
13 | if (rowKey == null || rowKey.isNull())
14 | throw new ModelException("Row Key is null");
15 | return rowKey.getBytes();
16 | }
17 |
18 | public static List validateRowKeys(List rowKeys) {
19 | for (Bytes b : rowKeys)
20 | validateRowKey(b);
21 | return rowKeys;
22 | }
23 |
24 | public static List validateRowKeysUtf8(List rowKeys) {
25 | for (String s : rowKeys)
26 | if (s == null)
27 | throw new ModelException("Row key is null");
28 | return rowKeys;
29 | }
30 |
31 | public static Bytes validateRowKey(Bytes rowKey) {
32 | if (rowKey == null || rowKey.isNull())
33 | throw new ModelException("Row Key is null");
34 | return rowKey;
35 | }
36 |
37 | public static void validateColumn(Column column) {
38 | if (!column.isSetName())
39 | throw new ModelException("Column name is null");
40 | if (!column.isSetValue())
41 | throw new ModelException("Column value is null");
42 | }
43 |
44 | public static void validateColumn(CounterColumn column) {
45 | if (!column.isSetName())
46 | throw new ModelException("Column name is null");
47 | if (!column.isSetValue())
48 | throw new ModelException("Column value is null");
49 | }
50 |
51 | public static void validateColumns(List columns) {
52 | for (Column c : columns) validateColumn(c);
53 | }
54 |
55 | public static void validateCounterColumns(List columns) {
56 | for (CounterColumn c : columns) validateColumn(c);
57 | }
58 |
59 | public static void validateColumnNames(List names) {
60 | for (Bytes n : names) validateColumnName(n);
61 | }
62 |
63 | public static void validateColumnName(Bytes name) {
64 | if (name == null || name.isNull())
65 | throw new ModelException("Column name is null");
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/exceptions/ApplicationException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.exceptions;
26 |
27 |
28 | public class ApplicationException extends PelopsException {
29 | public ApplicationException(Exception e) {
30 | super(e.getMessage(), e);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/exceptions/AuthenticationException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.exceptions;
26 |
27 | public class AuthenticationException extends PelopsException {
28 | public AuthenticationException(org.apache.cassandra.thrift.AuthenticationException e) {
29 | super(e.getWhy(), e);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/exceptions/AuthorizationException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.exceptions;
26 |
27 | public class AuthorizationException extends PelopsException {
28 | public AuthorizationException(org.apache.cassandra.thrift.AuthorizationException e) {
29 | super(e.getWhy(), e);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/exceptions/IExceptionTranslator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.exceptions;
26 |
27 | /**
28 | * Interface used to define how exception are translated.
29 | */
30 | public interface IExceptionTranslator {
31 | /**
32 | * Translate the provided exception into a pelops exception.
33 | * @param e the exception
34 | * @return the pelops exception
35 | */
36 | PelopsException translate(Exception e);
37 |
38 | /**
39 | * Default implementation.
40 | */
41 | public static class ExceptionTranslator implements IExceptionTranslator {
42 | @Override
43 | public PelopsException translate(Exception e) {
44 | if (e instanceof org.apache.cassandra.thrift.NotFoundException)
45 | return new NotFoundException(e);
46 | else if (e instanceof org.apache.cassandra.thrift.InvalidRequestException)
47 | return new InvalidRequestException((org.apache.cassandra.thrift.InvalidRequestException) e);
48 | else if (e instanceof org.apache.thrift.TApplicationException)
49 | return new ApplicationException(e);
50 | else if (e instanceof org.apache.cassandra.thrift.AuthenticationException)
51 | return new AuthenticationException((org.apache.cassandra.thrift.AuthenticationException) e);
52 | else if (e instanceof org.apache.cassandra.thrift.AuthorizationException)
53 | return new AuthorizationException((org.apache.cassandra.thrift.AuthorizationException) e);
54 | else if (e instanceof org.apache.cassandra.thrift.TimedOutException)
55 | return new TimedOutException(e);
56 | else if (e instanceof org.apache.thrift.transport.TTransportException)
57 | return new TransportException(e);
58 | else if (e instanceof org.apache.thrift.protocol.TProtocolException)
59 | return new ProtocolException(e);
60 | else if (e instanceof org.apache.cassandra.thrift.UnavailableException)
61 | return new UnavailableException(e);
62 | else if (e instanceof PelopsException)
63 | return (PelopsException) e; // don't re-wrap
64 | else
65 | return new PelopsException(e);
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/exceptions/InvalidRequestException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.exceptions;
26 |
27 | public class InvalidRequestException extends PelopsException {
28 | public InvalidRequestException(org.apache.cassandra.thrift.InvalidRequestException e) {
29 | super(e.getWhy(), e);
30 | }
31 |
32 | /**
33 | * @see org.apache.cassandra.thrift.InvalidRequestException#getWhy()
34 | */
35 | public String getWhy() {
36 | return ((org.apache.cassandra.thrift.InvalidRequestException) getCause()).getWhy();
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/exceptions/ModelException.java:
--------------------------------------------------------------------------------
1 | package org.scale7.cassandra.pelops.exceptions;
2 |
3 | public class ModelException extends ProtocolException {
4 |
5 | public ModelException(String message) {
6 | super(message);
7 | }
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/exceptions/NoConnectionsAvailableException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.exceptions;
26 |
27 | public class NoConnectionsAvailableException extends PelopsException {
28 | public NoConnectionsAvailableException() {
29 | }
30 |
31 | public NoConnectionsAvailableException(String s) {
32 | super(s);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/exceptions/NotFoundException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.exceptions;
26 |
27 | public class NotFoundException extends PelopsException {
28 | public NotFoundException(Exception e) {
29 | super(e.getMessage(), e);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/exceptions/PelopsException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.exceptions;
26 |
27 | /**
28 | * Base exception thrown by pelops.
29 | */
30 | public class PelopsException extends RuntimeException {
31 | public PelopsException() {
32 | }
33 |
34 | public PelopsException(String s) {
35 | super(s);
36 | }
37 |
38 | public PelopsException(String s, Throwable throwable) {
39 | super(s, throwable);
40 | }
41 |
42 | public PelopsException(Throwable throwable) {
43 | super(throwable);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/exceptions/ProtocolException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.exceptions;
26 |
27 | public class ProtocolException extends PelopsException {
28 |
29 | public ProtocolException(Exception e) {
30 | super(e.getMessage(), e);
31 | }
32 |
33 | public ProtocolException(String message) {
34 | super(message);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/exceptions/TimedOutException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.exceptions;
26 |
27 | public class TimedOutException extends PelopsException {
28 | public TimedOutException(Exception e) {
29 | super(e.getMessage(), e);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/exceptions/TransportException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.exceptions;
26 |
27 | public class TransportException extends PelopsException {
28 | public TransportException(Exception e) {
29 | super(e.getMessage(), e);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/exceptions/UnavailableException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.exceptions;
26 |
27 | public class UnavailableException extends PelopsException {
28 | public UnavailableException(Exception e) {
29 | super(e.getMessage(), e);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/pool/CommonsBackedPoolMBean.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.pool;
26 |
27 | public interface CommonsBackedPoolMBean {
28 | String JMX_MBEAN_OBJ_NAME = "com.scale7.cassandra.pelops.pool:type=Pool";
29 |
30 | /*
31 | RUNNING STATS
32 | */
33 |
34 | int getConnectionsCreated();
35 |
36 | int getConnectionsDestroyed();
37 |
38 | int getConnectionsCorrupted();
39 |
40 | int getConnectionsActive();
41 |
42 | int getNodesActive();
43 |
44 | int getNodesSuspended();
45 |
46 | int getConnectionsBorrowedTotal();
47 |
48 | int getConnectionsReleasedTotal();
49 |
50 | /*
51 | CONFIGURATION
52 | */
53 |
54 | public int getMaxActivePerNode();
55 |
56 | public void setMaxActivePerNode(int maxActivePerNode);
57 |
58 | public int getMaxIdlePerNode();
59 |
60 | public void setMaxIdlePerNode(int maxIdlePerNode);
61 |
62 | public int getMaxTotal();
63 |
64 | public void setMaxTotal(int maxTotal);
65 |
66 | public int getMinIdlePerNode();
67 |
68 | public void setMinIdlePerNode(int minIdlePerNode);
69 |
70 | public int getMaxWaitForConnection();
71 |
72 | public void setMaxWaitForConnection(int maxWaitForConnection);
73 |
74 | public boolean isTestConnectionsWhileIdle();
75 |
76 | public void setTestConnectionsWhileIdle(boolean testConnectionsWhileIdle);
77 |
78 | public int getNodeDownSuspensionMillis();
79 |
80 | public void setNodeDownSuspensionMillis(int nodeDownSuspensionMillis);
81 |
82 | /*
83 | OPERATIONS
84 | */
85 |
86 | void runMaintenanceTasks();
87 | }
88 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/pool/DebuggingPool.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.pool;
26 |
27 | import java.net.SocketException;
28 | import java.util.Random;
29 | import java.util.Set;
30 |
31 | import org.apache.cassandra.thrift.InvalidRequestException;
32 | import org.apache.thrift.TException;
33 | import org.scale7.cassandra.pelops.Cluster;
34 | import org.scale7.cassandra.pelops.Connection;
35 | import org.scale7.cassandra.pelops.OperandPolicy;
36 | import org.scale7.cassandra.pelops.exceptions.NoConnectionsAvailableException;
37 | import org.scale7.portability.SystemProxy;
38 | import org.slf4j.Logger;
39 |
40 | /**
41 | * A basic non-pooled pool impl. A new connection is opened each time the {@link #getConnection()} or
42 | * {@link IThriftPool#getConnectionExcept(java.util.Set)} is called.
43 | *
44 | * This class is useful for diagnostics.
45 | */
46 | public class DebuggingPool extends ThriftPoolBase {
47 | private static final Logger logger = SystemProxy.getLoggerFromFactory(DebuggingPool.class);
48 |
49 | private Cluster cluster;
50 | private String keyspace;
51 | private OperandPolicy generalPolicy;
52 | private Random random;
53 |
54 | PooledConnection connection = null;
55 |
56 | public DebuggingPool(Cluster cluster, String keyspace, OperandPolicy generalPolicy) {
57 | this.cluster = cluster;
58 | this.keyspace = keyspace;
59 | this.generalPolicy = generalPolicy;
60 |
61 | this.random = new Random();
62 | }
63 |
64 | @Override
65 | public IPooledConnection getConnection() throws NoConnectionsAvailableException {
66 | Cluster.Node[] nodes = cluster.getNodes();
67 | int index = nodes.length == 1 ? 0 : random.nextInt(nodes.length);
68 |
69 | logger.debug("Using node '{}'", nodes[index]);
70 |
71 | if (connection != null && connection.isOpen()) return connection;
72 |
73 | try {
74 | connection = new PooledConnection(nodes[index], keyspace);
75 | connection.open();
76 | } catch (Exception e) {
77 | throw new NoConnectionsAvailableException();
78 | }
79 |
80 | return connection;
81 | }
82 |
83 | @Override
84 | public IPooledConnection getConnectionExcept(Set avoidNodes) throws NoConnectionsAvailableException {
85 | return getConnection();
86 | }
87 |
88 | @Override
89 | public void shutdown() {
90 | // Do nothing.. we do not have a handle on number of unreleased connections
91 | }
92 |
93 | @Override
94 | public OperandPolicy getOperandPolicy() {
95 | return generalPolicy;
96 | }
97 |
98 | @Override
99 | public String getKeyspace() {
100 | return keyspace;
101 | }
102 |
103 | public class PooledConnection extends Connection implements IPooledConnection {
104 | public PooledConnection(Cluster.Node node, String keyspace) throws SocketException, TException, InvalidRequestException {
105 | super(node, keyspace);
106 | }
107 |
108 | @Override
109 | public void release() {
110 | }
111 |
112 | @Override
113 | public void corrupted() {
114 | close();
115 | }
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/pool/DescribeVersionConnectionValidator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.pool;
26 |
27 | import org.scale7.portability.SystemProxy;
28 | import org.slf4j.Logger;
29 |
30 | /**
31 | * A simple impl. that issues a call to {@link org.apache.cassandra.thrift.Cassandra.Client#describe_version} to
32 | * validate that the connection still works.
33 | */
34 | public class DescribeVersionConnectionValidator implements CommonsBackedPool.IConnectionValidator {
35 | private static final Logger logger = SystemProxy.getLoggerFromFactory(DescribeVersionConnectionValidator.class);
36 | /**
37 | * Returns true if the call to {@link org.apache.cassandra.thrift.Cassandra.Client#describe_version} succeeds.
38 | * @param connection the connection
39 | * @return true if the connection is valid, otherwise false
40 | */
41 | @Override
42 | public boolean validate(CommonsBackedPool.PooledConnection connection) {
43 | try {
44 | connection.getAPI().describe_version();
45 | } catch (Exception e) {
46 | logger.debug("Connection '{}' failed to validate", connection);
47 | return false;
48 | }
49 |
50 | logger.debug("Connection '{}' passed validation", connection);
51 | return true;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/pool/IThriftPool.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.pool;
26 |
27 | import java.util.Set;
28 |
29 | import org.scale7.cassandra.pelops.IConnection;
30 | import org.scale7.cassandra.pelops.Mutator;
31 | import org.scale7.cassandra.pelops.OperandPolicy;
32 | import org.scale7.cassandra.pelops.RowDeletor;
33 | import org.scale7.cassandra.pelops.Selector;
34 | import org.scale7.cassandra.pelops.exceptions.NoConnectionsAvailableException;
35 |
36 | /**
37 | * The contract for connection pools used by pelops.
38 | */
39 | public interface IThriftPool {
40 | /**
41 | * Create a {@link org.scale7.cassandra.pelops.Selector selector} object.
42 | *
43 | * @return A new {@link org.scale7.cassandra.pelops.Selector selector} object
44 | */
45 | Selector createSelector();
46 |
47 | /**
48 | * Create a {@link org.scale7.cassandra.pelops.Mutator mutator} object using the current time as the operation time stamp.
49 | * The {@link org.scale7.cassandra.pelops.Mutator mutator} object must only be used to execute 1 mutation operation.
50 | *
51 | * @return A new {@link org.scale7.cassandra.pelops.Mutator mutator} object
52 | */
53 | Mutator createMutator();
54 |
55 | /**
56 | * Create a {@link Mutator mutator} object with an arbitrary time stamp. The {@link Mutator mutator} object
57 | * must only be used to execute 1 mutation operation.
58 | * The created mutator will be created with the value of {@link org.scale7.cassandra.pelops.OperandPolicy#isDeleteIfNull()}.
59 | *
60 | * @param timestamp The default time stamp to use for operations
61 | * @return A new {@link Mutator mutator} object
62 | */
63 | Mutator createMutator(long timestamp);
64 |
65 | /**
66 | * Create a {@link Mutator mutator} object with an arbitrary time stamp. The {@link Mutator mutator} object
67 | * must only be used to execute 1 mutation operation.
68 | *
The created mutator will be created with the value of {@link org.scale7.cassandra.pelops.OperandPolicy#isDeleteIfNull()}.
69 | *
70 | * @param timestamp The default time stamp to use for operations
71 | * @param ttl the ttl (in seconds) that columns created using the various {@link Mutator#newColumn(org.scale7.cassandra.pelops.Bytes , org.scale7.cassandra.pelops.Bytes)} will default to
72 | * @return A new {@link Mutator mutator} object
73 | */
74 | Mutator createMutator(long timestamp, int ttl);
75 |
76 | /**
77 | * Create a {@link Mutator mutator} object with an arbitrary time stamp. The {@link Mutator mutator} object
78 | * must only be used to execute 1 mutation operation.
79 | *
80 | * @param timestamp The default time stamp to use for operations
81 | * @param deleteIfNull If true the mutator will default to issuing deletes when it detects null values on a column
82 | * passed to the various write methods.
83 | * @return A new {@link Mutator mutator} object
84 | */
85 | Mutator createMutator(long timestamp, boolean deleteIfNull);
86 |
87 | /**
88 | * Create a {@link Mutator mutator} object with an arbitrary time stamp. The {@link Mutator mutator} object
89 | * must only be used to execute 1 mutation operation.
90 | *
91 | * @param timestamp The default time stamp to use for operations
92 | * @param deleteIfNull If true the mutator will default to issuing deletes when it detects null values on a column
93 | * passed to the various write methods.
94 | * @param ttl the ttl (in seconds) that columns created using the various {@link Mutator#newColumn(org.scale7.cassandra.pelops.Bytes , org.scale7.cassandra.pelops.Bytes)} will default to
95 | * @return A new {@link Mutator mutator} object
96 | */
97 | Mutator createMutator(long timestamp, boolean deleteIfNull, int ttl);
98 |
99 | /**
100 | * Create a {@link org.scale7.cassandra.pelops.RowDeletor key deletor} object using the current time as the operation time stamp.
101 | *
102 | * @return A new {@link org.scale7.cassandra.pelops.RowDeletor key deletor} object
103 | */
104 | RowDeletor createRowDeletor();
105 |
106 | /**
107 | * Create a {@link RowDeletor key deletor} object with an arbitrary time stamp.
108 | *
109 | * @param timestamp The default time stamp to use for operations
110 | * @return A new {@link RowDeletor key deletor} object
111 | */
112 | RowDeletor createRowDeletor(long timestamp);
113 |
114 | /**
115 | * Get a connection from the pool.
116 | *
117 | * @return the connection
118 | * @throws NoConnectionsAvailableException if an error occurs
119 | */
120 | IPooledConnection getConnection() throws NoConnectionsAvailableException;
121 |
122 | /**
123 | * Get a connection from the pool trying to avoid the nodes specified by the avoidNodes param.
124 | *
125 | *
126 | * @param avoidNodes the nodes to avoid if possible (may be null)
127 | * @return the connection
128 | * @throws NoConnectionsAvailableException if an error occurs
129 | */
130 | IPooledConnection getConnectionExcept(Set avoidNodes) throws NoConnectionsAvailableException;
131 |
132 | /**
133 | * Shuts down the pool.
134 | *
135 | * Calling this method after the pool has been shutdown should have no affect.
136 | */
137 | void shutdown();
138 |
139 | /**
140 | * Get the current policy in force, which controls the general behavior of pelops.
141 | *
142 | * @return the current policy
143 | */
144 | OperandPolicy getOperandPolicy();
145 |
146 | /**
147 | * The keyspace this connection operates on.
148 | *
149 | * @return the keyspace
150 | */
151 | String getKeyspace();
152 |
153 | /**
154 | * Defines an encapsulation for a connection to a Cassandra node.
155 | *
156 | * @author dominicwilliams
157 | * @author danwashusen
158 | */
159 | interface IPooledConnection extends IConnection {
160 | /**
161 | * Release a Connection
that has previously been taken from the pool.
162 | */
163 | void release();
164 |
165 | /**
166 | * Specify whether an exception has been thrown during usage of the connection. If an exception has been thrown, the
167 | * connection will not re-used since it may be corrupted (for example, it may contain partially written
168 | * data that disrupts the serialization of the Thrift protocol) however it is remains essential that all
169 | * connection objects are released.
170 | */
171 | void corrupted();
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/pool/LeastLoadedNodeSelectionStrategy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.pool;
26 |
27 | import java.util.ArrayList;
28 | import java.util.Collections;
29 | import java.util.List;
30 | import java.util.Set;
31 |
32 | import org.scale7.portability.SystemProxy;
33 | import org.slf4j.Logger;
34 |
35 | /**
36 | * Selects a node based on the number of connections a node currently has in use. The node that has the least active
37 | * connections will be chosen.
38 | */
39 | public class LeastLoadedNodeSelectionStrategy implements CommonsBackedPool.INodeSelectionStrategy {
40 | private static final Logger logger = SystemProxy.getLoggerFromFactory(LeastLoadedNodeSelectionStrategy.class);
41 |
42 | @Override
43 | public PooledNode select(CommonsBackedPool pool, Set nodeAddresses, Set avoidNodesHint) {
44 | // create a candidate list (otherwise the numActive could change while sorting)
45 | if (logger.isDebugEnabled())
46 | logger.debug("Determining which node is the least loaded");
47 | List candidates = new ArrayList(nodeAddresses.size());
48 | for (String nodeAddress : nodeAddresses) {
49 | PooledNode pooledNode = pool.getPooledNode(nodeAddress);
50 | if (pooledNode == null || pooledNode.isSuspended()) {
51 | if (logger.isDebugEnabled())
52 | logger.debug("Excluding node '{}' because it's either been removed from the pool or has been suspended", nodeAddress);
53 | continue;
54 | }
55 |
56 | candidates.add(new Candidate(pooledNode.getAddress(), pooledNode));
57 | }
58 |
59 | // make sure there's at least one node to choose from after filtering out suspended nodes etc
60 | if (candidates.isEmpty())
61 | return null;
62 | if (candidates.size() == 1)
63 | return pool.getPooledNode(candidates.iterator().next().address);
64 |
65 | // sort to find the node with the least active connections
66 | Collections.sort(candidates);
67 |
68 | // pick a node (trying to honor the notNodeHint)
69 | PooledNode node = null;
70 | for (Candidate candidate : candidates) {
71 | node = pool.getPooledNode(candidate.address);
72 | if (avoidNodesHint == null || !avoidNodesHint.contains(candidate.address)) {
73 | break;
74 | } else {
75 | if (logger.isDebugEnabled())
76 | logger.debug("Attempting to honor the avoidNodesHint '{}', skipping node '{}'", avoidNodesHint, candidate.address);
77 | continue;
78 | }
79 | }
80 |
81 | if (logger.isDebugEnabled())
82 | logger.debug("Chose node '{}'...", node != null ? node.getAddress() : "null");
83 |
84 | return node;
85 | }
86 |
87 | public class Candidate implements Comparable {
88 | public Candidate(String address, PooledNode node) {
89 | this.address = address;
90 | this.numActive = node.getNumActive();
91 | this.numBorrowed = node.getConnectionsBorrowedTotal();
92 | this.numCorrupted = node.getConnectionsCorrupted();
93 |
94 | if (logger.isDebugEnabled())
95 | logger.debug("Node '{}' has {} active connections, {} borrowed connections and {} corrupted connections", new Object[] {address, numActive, numBorrowed, numCorrupted});
96 | }
97 |
98 | String address;
99 | int numActive;
100 | int numBorrowed;
101 | int numCorrupted;
102 |
103 | @Override
104 | public int compareTo(Candidate candidate) {
105 | int value = numActive - candidate.numActive;
106 |
107 | if (value == 0)
108 | value = numBorrowed - candidate.numBorrowed;
109 |
110 | if (value == 0)
111 | value = numCorrupted - candidate.numCorrupted;
112 |
113 | return value;
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/pool/NoOpConnectionValidator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.pool;
26 |
27 | /**
28 | * A connection validator that doesn't validate the connection.
29 | */
30 | public class NoOpConnectionValidator implements CommonsBackedPool.IConnectionValidator {
31 | /**
32 | * Returns true.
33 | * @param connection the connection
34 | * @return true
35 | */
36 | @Override
37 | public boolean validate(CommonsBackedPool.PooledConnection connection) {
38 | return true;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/pool/NoOpNodeSuspensionStrategy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.pool;
26 |
27 | /**
28 | * An implementation of the {@link CommonsBackedPool.INodeSuspensionStrategy} that does nothing.
29 | */
30 | public class NoOpNodeSuspensionStrategy implements CommonsBackedPool.INodeSuspensionStrategy {
31 | @Override
32 | public boolean evaluate(CommonsBackedPool pool, PooledNode node) {
33 | return false;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/pool/PooledNode.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.pool;
26 |
27 | import java.util.concurrent.atomic.AtomicInteger;
28 | import java.util.concurrent.locks.Lock;
29 | import java.util.concurrent.locks.ReentrantReadWriteLock;
30 |
31 | import org.scale7.cassandra.pelops.JmxMBeanManager;
32 | import org.scale7.portability.SystemProxy;
33 | import org.slf4j.Logger;
34 |
35 | /**
36 | * A pooled node class used by the {@link org.scale7.cassandra.pelops.pool.CommonsBackedPool}.
37 | */
38 | public class PooledNode implements PooledNodeMBean {
39 | private static final Logger logger = SystemProxy.getLoggerFromFactory(CommonsBackedPool.class);
40 | private CommonsBackedPool pool;
41 | private String address;
42 |
43 | private CommonsBackedPool.INodeSuspensionState suspensionState;
44 | private final ReentrantReadWriteLock suspensionStateLock = new ReentrantReadWriteLock();
45 | private final Lock suspensionStateReadLock = suspensionStateLock.readLock();
46 | private final Lock suspensionStateWriteLock = suspensionStateLock.writeLock();
47 |
48 | private AtomicInteger suspensions;
49 | private AtomicInteger connectionsCorrupted;
50 | private AtomicInteger connectionsCreated;
51 | private AtomicInteger connectionsDestroyed;
52 | private AtomicInteger connectionsBorrowedTotal;
53 | private AtomicInteger connectionsReleasedTotal;
54 |
55 | PooledNode(CommonsBackedPool pool, String address) {
56 | this.pool = pool;
57 | this.address = address;
58 | suspensions = new AtomicInteger();
59 | connectionsCorrupted = new AtomicInteger();
60 | connectionsCreated = new AtomicInteger();
61 | connectionsDestroyed = new AtomicInteger();
62 | connectionsBorrowedTotal = new AtomicInteger();
63 | connectionsReleasedTotal = new AtomicInteger();
64 |
65 | String beanName = getMBeanName();
66 | if (JmxMBeanManager.getInstance().isRegistered(beanName)) {
67 | logger.warn("MBean '{}' is already registered, removing...", beanName);
68 | JmxMBeanManager.getInstance().unregisterMBean(beanName);
69 | }
70 |
71 | logger.info("Registering MBean '{}'...", beanName);
72 | JmxMBeanManager.getInstance().registerMBean(this, beanName);
73 | }
74 |
75 | public void decommission() {
76 | String beanName = getMBeanName();
77 | logger.info("Removing MBean '{}'...", beanName);
78 | if (JmxMBeanManager.getInstance().isRegistered(beanName))
79 | JmxMBeanManager.getInstance().unregisterMBean(beanName);
80 | }
81 |
82 | @Override
83 | public String getAddress() {
84 | return address;
85 | }
86 |
87 | public CommonsBackedPool.INodeSuspensionState getSuspensionState() {
88 | try {
89 | suspensionStateReadLock.lock();
90 | return suspensionState;
91 | } finally {
92 | suspensionStateReadLock.unlock();
93 | }
94 | }
95 |
96 | public void setSuspensionState(CommonsBackedPool.INodeSuspensionState suspensionState) {
97 | try {
98 | suspensionStateWriteLock.lock();
99 | this.suspensionState = suspensionState;
100 | } finally {
101 | suspensionStateWriteLock.unlock();
102 | }
103 | }
104 |
105 | void reportSuspension() {
106 | suspensions.incrementAndGet();
107 | }
108 |
109 | @Override
110 | public int getSuspensions() {
111 | return suspensions.get();
112 | }
113 |
114 | @Override
115 | @SuppressWarnings("unchecked")
116 | public int getNumActive() {
117 | return pool.getUnderlyingPool().getNumActive(address);
118 | }
119 |
120 | @Override
121 | @SuppressWarnings("unchecked")
122 | public int getNumIdle() {
123 | return pool.getUnderlyingPool().getNumIdle(address);
124 | }
125 |
126 | void reportConnectionCorrupted() {
127 | connectionsCorrupted.incrementAndGet();
128 | }
129 |
130 | @Override
131 | public int getConnectionsCorrupted() {
132 | return connectionsCorrupted.get();
133 | }
134 |
135 | void reportConnectionCreated() {
136 | connectionsCreated.incrementAndGet();
137 | }
138 |
139 | @Override
140 | public int getConnectionsCreated() {
141 | return connectionsCreated.get();
142 | }
143 |
144 | void reportConnectionDestroyed() {
145 | connectionsDestroyed.incrementAndGet();
146 | }
147 |
148 | @Override
149 | public int getConnectionsDestroyed() {
150 | return connectionsDestroyed.get();
151 | }
152 |
153 | void reportConnectionBorrowed() {
154 | connectionsBorrowedTotal.incrementAndGet();
155 | }
156 |
157 | @Override
158 | public int getConnectionsBorrowedTotal() {
159 | return connectionsBorrowedTotal.get();
160 | }
161 |
162 | void reportConnectionReleased() {
163 | connectionsReleasedTotal.incrementAndGet();
164 | }
165 |
166 | @Override
167 | public int getConnectionsReleasedTotal() {
168 | return connectionsReleasedTotal.get();
169 | }
170 |
171 | @Override
172 | public boolean isSuspended() {
173 | try {
174 | suspensionStateReadLock.lock();
175 | CommonsBackedPool.INodeSuspensionState state = getSuspensionState();
176 | return state != null && state.isSuspended();
177 | } finally {
178 | suspensionStateReadLock.unlock();
179 | }
180 | }
181 |
182 | @Override
183 | public void suspendIndefinetily() {
184 | setSuspensionState(TimeBasedSuspensionState.indefinetily());
185 | reportSuspension();
186 | }
187 |
188 | @Override
189 | public void suspendForMillis(long nodeSuspensionMillis) {
190 | setSuspensionState(TimeBasedSuspensionState.millisFromNow(nodeSuspensionMillis));
191 | reportSuspension();
192 | }
193 |
194 | @Override
195 | public void clearSuspensionState() {
196 | setSuspensionState(null);
197 | }
198 |
199 | private String getMBeanName() {
200 | return JMX_MBEAN_OBJ_NAME + "-" + pool.getKeyspace() + "-" + getAddress();
201 | }
202 |
203 | public static class TimeBasedSuspensionState implements CommonsBackedPool.INodeSuspensionState {
204 | private long suspendedUntil;
205 |
206 | private TimeBasedSuspensionState(long suspendedUntil) {
207 | this.suspendedUntil = suspendedUntil;
208 | }
209 |
210 | @Override
211 | public boolean isSuspended() {
212 | return suspendedUntil >= System.currentTimeMillis();
213 | }
214 |
215 | public static CommonsBackedPool.INodeSuspensionState millisFromNow(long millisFromNow) {
216 | return new TimeBasedSuspensionState(System.currentTimeMillis() + millisFromNow);
217 | }
218 |
219 | public static CommonsBackedPool.INodeSuspensionState indefinetily() {
220 | return new TimeBasedSuspensionState(Long.MAX_VALUE);
221 | }
222 | }
223 | }
224 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/pool/PooledNodeMBean.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.pool;
26 |
27 | public interface PooledNodeMBean {
28 | String JMX_MBEAN_OBJ_NAME = "com.scale7.cassandra.pelops.pool:type=PooledNode";
29 |
30 | String getAddress();
31 |
32 | int getSuspensions();
33 |
34 | int getNumActive();
35 |
36 | int getNumIdle();
37 |
38 | int getConnectionsCorrupted();
39 |
40 | int getConnectionsCreated();
41 |
42 | int getConnectionsDestroyed();
43 |
44 | int getConnectionsBorrowedTotal();
45 |
46 | int getConnectionsReleasedTotal();
47 |
48 | boolean isSuspended();
49 |
50 | void suspendIndefinetily();
51 |
52 | void suspendForMillis(long nodeSuspensionMillis);
53 |
54 | void clearSuspensionState();
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/pool/ThriftPoolBase.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.pool;
26 |
27 | import org.scale7.cassandra.pelops.Mutator;
28 | import org.scale7.cassandra.pelops.RowDeletor;
29 | import org.scale7.cassandra.pelops.Selector;
30 |
31 |
32 | /**
33 | * Abstract impl of {@link org.scale7.cassandra.pelops.pool.IThriftPool}.
34 | */
35 | public abstract class ThriftPoolBase implements IThriftPool {
36 | /**
37 | * {@inheritDoc}.
38 | */
39 | @Override
40 | public Selector createSelector() {
41 | validateKeyspaceSet();
42 | return new Selector(this);
43 | }
44 |
45 | /**
46 | * {@inheritDoc}.
47 | */
48 | @Override
49 | public Mutator createMutator() {
50 | validateKeyspaceSet();
51 | return new Mutator(this);
52 | }
53 |
54 | /**
55 | * {@inheritDoc}.
56 | */
57 | @Override
58 | public Mutator createMutator(long timestamp) {
59 | return createMutator(timestamp, this.getOperandPolicy().isDeleteIfNull());
60 | }
61 |
62 | @Override
63 | public Mutator createMutator(long timestamp, int ttl) {
64 | return createMutator(timestamp, this.getOperandPolicy().isDeleteIfNull(), ttl);
65 | }
66 |
67 | /**
68 | * {@inheritDoc}.
69 | */
70 | @Override
71 | public Mutator createMutator(long timestamp, boolean deleteIfNull) {
72 | validateKeyspaceSet();
73 | return new Mutator(this, timestamp, deleteIfNull);
74 | }
75 |
76 | @Override
77 | public Mutator createMutator(long timestamp, boolean deleteIfNull, int ttl) {
78 | validateKeyspaceSet();
79 | return new Mutator(this, timestamp, this.getOperandPolicy().isDeleteIfNull(), ttl);
80 | }
81 |
82 | /**
83 | * {@inheritDoc}.
84 | */
85 | @Override
86 | public RowDeletor createRowDeletor() {
87 | validateKeyspaceSet();
88 | return new RowDeletor(this);
89 | }
90 |
91 | /**
92 | * {@inheritDoc}.
93 | */
94 | @Override
95 | public RowDeletor createRowDeletor(long timestamp) {
96 | validateKeyspaceSet();
97 | return new RowDeletor(this, timestamp);
98 | }
99 |
100 | private void validateKeyspaceSet() throws IllegalStateException {
101 | if (getKeyspace() == null && getKeyspace().isEmpty()) {
102 | throw new IllegalStateException("A keyspace must be provided in order to use this function.");
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/spring/CommonsBackedPoolFactoryBean.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops.spring;
26 |
27 | import java.util.Arrays;
28 |
29 | import org.scale7.cassandra.pelops.Cluster;
30 | import org.scale7.cassandra.pelops.OperandPolicy;
31 | import org.scale7.cassandra.pelops.pool.CommonsBackedPool;
32 | import org.scale7.cassandra.pelops.pool.IThriftPool;
33 | import org.scale7.portability.SystemProxy;
34 | import org.slf4j.Logger;
35 | import org.springframework.beans.factory.DisposableBean;
36 | import org.springframework.beans.factory.FactoryBean;
37 | import org.springframework.beans.factory.InitializingBean;
38 | import org.springframework.beans.factory.annotation.Required;
39 | import org.springframework.util.Assert;
40 |
41 | /**
42 | * Used to initialize a Pelops pool that honors Spring's context life cycle. Using this class ensures that the
43 | * dependency graph that's managed by Spring won't attempt to use Pelops when it isn't available.
44 | *
45 | * To use it add the following to your context file:
46 | *
47 | * <bean id="pelopsPool" class="org.scale7.cassandra.pelops.spring.CommonsBackedPoolFactoryBean">
48 | * <property name="cluster">
49 | * <bean class="org.scale7.cassandra.pelops.Cluster">
50 | * <constructor-arg index="0" type="java.lang.String" value="${digitalpigeon.cassandra.host}" />
51 | * <constructor-arg index="1" type="int" value="${digitalpigeon.cassandra.port}" />
52 | * </bean>
53 | * </property>
54 | * <property name="keyspace" value="keyspace" />
55 | * </bean>
56 | *
57 | *
58 | *
59 | * NOTE: If you intend to use this class you'll need to bypass the static convenience methods on
60 | * {@link org.scale7.cassandra.pelops.Pelops}.
61 | * Inject the instance of {@link org.scale7.cassandra.pelops.pool.IThriftPool} created by this factory bean into your
62 | * application code and use it's method directly.
63 | * For example:
64 | *
65 | * private IThriftPool pool;
66 | *
67 | *
68 | * public void doStuff() {
69 | * Selector selector = pool.createSelector();
70 | * ...
71 | * }
72 | *
73 | *
74 | *
75 | * Note: the use of the class required the *optional* spring dependency.
76 | */
77 | public class CommonsBackedPoolFactoryBean
78 | implements FactoryBean, InitializingBean, DisposableBean {
79 | private static final Logger logger = SystemProxy.getLoggerFromFactory(CommonsBackedPoolFactoryBean.class);
80 |
81 | private Cluster cluster;
82 | private String keyspace;
83 | private CommonsBackedPool.Policy policy;
84 | private OperandPolicy operandPolicy;
85 | private CommonsBackedPool.INodeSelectionStrategy nodeSelectionStrategy;
86 | private CommonsBackedPool.INodeSuspensionStrategy nodeSuspensionStrategy;
87 | private CommonsBackedPool.IConnectionValidator connectionValidator;
88 |
89 | private IThriftPool thriftPool;
90 |
91 | /**
92 | * {@inheritDoc}.
93 | * @return the pool
94 | */
95 | @Override
96 | public IThriftPool getObject() throws Exception {
97 | return thriftPool;
98 | }
99 |
100 | /**
101 | * {@inheritDoc}.
102 | * @return {@link IThriftPool}
103 | */
104 | @Override
105 | public Class> getObjectType() {
106 | return IThriftPool.class;
107 | }
108 |
109 | /**
110 | * {@inheritDoc}.
111 | * @return true
112 | */
113 | @Override
114 | public boolean isSingleton() {
115 | return true;
116 | }
117 |
118 | /**
119 | * Initializes the Pelops pool.
120 | * @throws Exception if an error occurs
121 | */
122 | @Override
123 | public void afterPropertiesSet() throws Exception {
124 | Assert.notNull(getCluster(), "The cluster property is required");
125 | Assert.notNull(getKeyspace(), "The keyspace property is required");
126 |
127 | logger.info("Initializing Pelops pool keyspace {} for nodes {}", getKeyspace(), Arrays.toString(getCluster().getNodes()));
128 |
129 | this.thriftPool = new CommonsBackedPool(
130 | getCluster(), getKeyspace(), getPolicy(), getOperandPolicy(), getNodeSelectionStrategy(),
131 | getNodeSuspensionStrategy(), getConnectionValidator()
132 | );
133 | }
134 |
135 | /**
136 | * Shuts down the Pelops pool.
137 | * @throws Exception if an error occurs
138 | * @see {@link org.scale7.cassandra.pelops.pool.IThriftPool#shutdown()}
139 | */
140 | @Override
141 | public void destroy() throws Exception {
142 | this.thriftPool.shutdown();
143 | }
144 |
145 | public Cluster getCluster() {
146 | return cluster;
147 | }
148 |
149 | @Required
150 | public void setCluster(Cluster cluster) {
151 | this.cluster = cluster;
152 | }
153 |
154 | public String getKeyspace() {
155 | return keyspace;
156 | }
157 |
158 | @Required
159 | public void setKeyspace(String keyspace) {
160 | this.keyspace = keyspace;
161 | }
162 |
163 | public CommonsBackedPool.Policy getPolicy() {
164 | return policy;
165 | }
166 |
167 | public void setPolicy(CommonsBackedPool.Policy policy) {
168 | this.policy = policy;
169 | }
170 |
171 | public OperandPolicy getOperandPolicy() {
172 | return operandPolicy;
173 | }
174 |
175 | public void setOperandPolicy(OperandPolicy operandPolicy) {
176 | this.operandPolicy = operandPolicy;
177 | }
178 |
179 | public CommonsBackedPool.INodeSelectionStrategy getNodeSelectionStrategy() {
180 | return nodeSelectionStrategy;
181 | }
182 |
183 | public void setNodeSelectionStrategy(CommonsBackedPool.INodeSelectionStrategy nodeSelectionStrategy) {
184 | this.nodeSelectionStrategy = nodeSelectionStrategy;
185 | }
186 |
187 | public CommonsBackedPool.INodeSuspensionStrategy getNodeSuspensionStrategy() {
188 | return nodeSuspensionStrategy;
189 | }
190 |
191 | public void setNodeSuspensionStrategy(CommonsBackedPool.INodeSuspensionStrategy nodeSuspensionStrategy) {
192 | this.nodeSuspensionStrategy = nodeSuspensionStrategy;
193 | }
194 |
195 | public CommonsBackedPool.IConnectionValidator getConnectionValidator() {
196 | return connectionValidator;
197 | }
198 |
199 | public void setConnectionValidator(CommonsBackedPool.IConnectionValidator connectionValidator) {
200 | this.connectionValidator = connectionValidator;
201 | }
202 | }
203 |
--------------------------------------------------------------------------------
/src/main/java/org/scale7/cassandra/pelops/types/CompositeType.java:
--------------------------------------------------------------------------------
1 | package org.scale7.cassandra.pelops.types;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.IOException;
5 | import java.nio.ByteBuffer;
6 | import java.util.ArrayList;
7 | import java.util.Arrays;
8 | import java.util.List;
9 | import java.util.UUID;
10 |
11 | import org.scale7.cassandra.pelops.Bytes;
12 | import org.scale7.cassandra.pelops.Bytes.BufferHelper;
13 | import org.slf4j.Logger;
14 | import org.slf4j.LoggerFactory;
15 |
16 | /**
17 | * CompositeType utility class
18 | *
19 | * @author Ali Serghini
20 | */
21 | public class CompositeType {
22 |
23 | private static final byte COMPONENT_END = (byte) 0;
24 | private static final Logger LOGGER = LoggerFactory.getLogger(CompositeType.class);
25 |
26 | //Utility class
27 | private CompositeType() {
28 | }
29 |
30 | /**
31 | * A Builder class that creates a CompositeType.
32 | */
33 | public static class Builder {
34 |
35 | private List parts = null;
36 |
37 | private Builder(int count) {
38 | parts = new ArrayList(count);
39 | }
40 |
41 | /**
42 | * Creates a new builder
43 | *
44 | * @param partsCount - CompositeType parts count. Should be 2 or more.
45 | * @return CompositeType builder
46 | */
47 | public static Builder newBuilder(int partsCount) {
48 | if (partsCount < 1) throw new IllegalArgumentException("Invalid parts count. Should be 2 or more.");
49 | return new Builder(partsCount);
50 | }
51 |
52 | /**
53 | * Creates a new builder. Assumes that there will be 2 elements in the composite type
54 | *
55 | * @return CompositeType builder
56 | */
57 | public static Builder newBuilder() {
58 | return new Builder(2);
59 | }
60 |
61 | public Builder addByteBuffer(ByteBuffer value) {
62 | parts.add(value);
63 | return this;
64 | }
65 |
66 | public Builder addBytes(Bytes value) {
67 | return addByteBuffer(value.getBytes());
68 | }
69 |
70 | public Builder addBoolean(boolean value) {
71 | return addByteBuffer(BufferHelper.fromBoolean(value));
72 | }
73 |
74 | public Builder addBoolean(Boolean value) {
75 | return addByteBuffer(BufferHelper.fromBoolean(value));
76 | }
77 |
78 | public Builder addByte(byte value) {
79 | return addByteBuffer(BufferHelper.fromByte(value));
80 | }
81 |
82 | public Builder addByte(Byte value) {
83 | return addByteBuffer(BufferHelper.fromByte(value));
84 | }
85 |
86 | public Builder addByteArray(byte[] value) {
87 | return addByteBuffer(BufferHelper.fromByteArray(value));
88 | }
89 |
90 | public Builder addChar(char value) {
91 | return addByteBuffer(BufferHelper.fromChar(value));
92 | }
93 |
94 | public Builder addChar(Character value) {
95 | return addByteBuffer(BufferHelper.fromChar(value));
96 | }
97 |
98 | public Builder addDouble(double value) {
99 | return addByteBuffer(BufferHelper.fromDouble(value));
100 | }
101 |
102 | public Builder addDouble(Double value) {
103 | return addByteBuffer(BufferHelper.fromDouble(value));
104 | }
105 |
106 | public Builder addFloat(float value) {
107 | return addByteBuffer(BufferHelper.fromFloat(value));
108 | }
109 |
110 | public Builder addFloat(Float value) {
111 | return addByteBuffer(BufferHelper.fromFloat(value));
112 | }
113 |
114 | public Builder addInt(int value) {
115 | return addByteBuffer(BufferHelper.fromInt(value));
116 | }
117 |
118 | public Builder addInt(Integer value) {
119 | return addByteBuffer(BufferHelper.fromInt(value));
120 | }
121 |
122 | public Builder addLong(long value) {
123 | return addByteBuffer(BufferHelper.fromLong(value));
124 | }
125 |
126 | public Builder addLong(Long value) {
127 | return addByteBuffer(BufferHelper.fromLong(value));
128 | }
129 |
130 | public Builder addShort(short value) {
131 | return addByteBuffer(BufferHelper.fromShort(value));
132 | }
133 |
134 | public Builder addShort(Short value) {
135 | return addByteBuffer(BufferHelper.fromShort(value));
136 | }
137 |
138 | public Builder addUTF8(String str) {
139 | return addByteBuffer(BufferHelper.fromUTF8(str));
140 | }
141 |
142 | public Builder addUuid(UUID value) {
143 | return addByteBuffer(BufferHelper.fromUuid(value));
144 | }
145 |
146 | public Builder addUuid(String value) {
147 | return addByteBuffer(BufferHelper.fromUuid(value));
148 | }
149 |
150 | public Builder addUuid(long msb, long lsb) {
151 | return addByteBuffer(BufferHelper.fromUuid(msb, lsb));
152 | }
153 |
154 | public Builder addTimeUuid(com.eaio.uuid.UUID value) {
155 | return addByteBuffer(BufferHelper.fromUuid(value.getTime(), value.getClockSeqAndNode()));
156 | }
157 |
158 | /**
159 | * Reset the builder
160 | */
161 | public void clear() {
162 | parts.clear();
163 | }
164 |
165 | /**
166 | * Build the CompositeType using the added parts.
167 | *
168 | * @return CompositeType as Bytes
169 | */
170 | public Bytes build() {
171 | if (parts == null || parts.isEmpty()) return null;
172 |
173 | final ByteArrayOutputStream bos = new ByteArrayOutputStream();
174 | for (ByteBuffer part : parts) {
175 | if (!part.hasArray())
176 | throw new IllegalStateException("Connot build CompositeType. Invalid composite byte part encountered");
177 |
178 | bos.write((byte) ((part.array().length >> (7 + 1)) & 0xFF));
179 | bos.write((byte) (part.array().length & 0xFF));
180 | for (byte partByte : part.array()) {
181 | bos.write(partByte & 0xFF);
182 | }
183 |
184 | bos.write(COMPONENT_END);
185 | }
186 |
187 | final Bytes bytes = Bytes.fromByteArray(bos.toByteArray());
188 |
189 | try {
190 | bos.close();
191 | } catch (IOException ex) {
192 | LOGGER.error("Failed to close the compostite type output stream", ex);
193 | }
194 |
195 | return bytes;
196 | }
197 | }
198 |
199 | /**
200 | * Parses the CompositeType
201 | *
202 | * @param compositeKey - composite key as Bytes
203 | * @return list of the composite key elements
204 | */
205 | public static List parse(Bytes compositeKey) {
206 | if (compositeKey == null) return null;
207 | return parse(compositeKey.toByteArray());
208 | }
209 |
210 | /**
211 | * Parses the CompositeType
212 | *
213 | * @param compositeKey - composite key as byte array
214 | * @return list of the composite key elements
215 | */
216 | public static List parse(byte[] compositeKey) {
217 | if (compositeKey == null) return null;
218 |
219 | //Validate the array length
220 | if (compositeKey.length < 2) throw new IllegalArgumentException("Invalid Composite type structure");
221 |
222 | final List list = new ArrayList(3);//Default to 3
223 | int ndx = 0;
224 | int componentStartNdx = 0;
225 | int componentEndNdx = 0;
226 | short componentLength = 0;
227 | while (compositeKey.length > (componentStartNdx = (ndx + 2))) {
228 | // Value length is a 2 bytes short
229 | componentLength = ByteBuffer.wrap(Arrays.copyOfRange(compositeKey, ndx, componentStartNdx)).getShort();
230 | componentEndNdx = componentStartNdx + componentLength;
231 |
232 | // Check if the component legth is valid
233 | if (compositeKey.length < componentEndNdx + 1) throw new IllegalStateException("Invalid Composite type structure");
234 | // If the value is not properly terminated throw an exception
235 | if (compositeKey[componentEndNdx] != COMPONENT_END)
236 | throw new IllegalStateException("Invalid Composite type structure: Not properly terminated, should be 0 byte terminated, found " + compositeKey[componentEndNdx]);
237 |
238 | // Get the value
239 | list.add(Arrays.copyOfRange(compositeKey, componentStartNdx, componentEndNdx));
240 |
241 | // Update the value of the index
242 | ndx = componentEndNdx + 1;
243 | }
244 |
245 | return list;
246 | }
247 | }
248 |
--------------------------------------------------------------------------------
/src/test/java/org/scale7/cassandra/pelops/ClusterUnitTest.java:
--------------------------------------------------------------------------------
1 | package org.scale7.cassandra.pelops;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertNotNull;
5 | import static org.junit.Assert.assertNull;
6 |
7 | import org.apache.cassandra.thrift.AuthenticationRequest;
8 | import org.junit.Test;
9 |
10 | /**
11 | * Tests the {@link org.scale7.cassandra.pelops.Cluster} class.
12 | */
13 | public class ClusterUnitTest {
14 |
15 | private static final String USERNAME = "tester";
16 | private static final String PASSWORD = "password";
17 |
18 | /**
19 | * Tests that if multiple nodes are provided in a single string that they it is processed correctly.
20 | */
21 | @Test
22 | public void testConstructorNodesSplit() {
23 | String[] nodes = new String[] {"node1", "node2", "node3"};
24 |
25 | Cluster cluster = new Cluster(nodes[0] + ", " + nodes[1] + ", " + nodes[2], 5555, false);
26 | Cluster.Node[] resultingNodes = cluster.getNodes();
27 | assertEquals("Incorrect wrong number of contact nodes", 3, resultingNodes.length);
28 | for (int i = 0; i < nodes.length; i++) {
29 | assertEquals("Node did not match", nodes[i], resultingNodes[i].getAddress());
30 | }
31 | }
32 |
33 | /**
34 | * Tests that if a single node is provided in a single string that it is processed correctly.
35 | */
36 | @Test
37 | public void testConstructorNodesSplitSingleNode() {
38 | String node = "node1";
39 | Cluster cluster = new Cluster(node, 5555, false);
40 | Cluster.Node[] resultingNodes = cluster.getNodes();
41 | assertEquals("Incorrect wrong number of contact nodes", 1, resultingNodes.length);
42 | assertEquals("Node did not match", node, resultingNodes[0].getAddress());
43 | }
44 |
45 | /**
46 | * Tests that a connection authenticator on a cluster is configured correctly
47 | */
48 | @Test
49 | public void testClusterNodeConnectionAuthenticator() {
50 | String node = "node1";
51 | Cluster cluster = new Cluster(node, 5555, false, new SimpleConnectionAuthenticator(USERNAME,PASSWORD));
52 | assertNotNull("Incorrect connection authentication config",cluster.getConnectionConfig().getConnectionAuthenticator());
53 | assertEquals("Incorrect connection authenticator class"
54 | ,cluster.getConnectionConfig().getConnectionAuthenticator().getClass(),SimpleConnectionAuthenticator.class);
55 | AuthenticationRequest request = cluster.getConnectionConfig().getConnectionAuthenticator().getAuthenticationRequest();
56 | assertNotNull("Invalid authentication request",request);
57 | assertNotNull("Invalid authentication request credentials",request.getCredentials());
58 | assertEquals("Invalid authentication username",request.getCredentials().get(SimpleConnectionAuthenticator.USERNAME_KEY),USERNAME);
59 | assertEquals("Invalid authentication username",request.getCredentials().get(SimpleConnectionAuthenticator.PASSWORD_KEY),PASSWORD);
60 | }
61 |
62 | /**
63 | * Tests that a cluster without a connection authenticator returns a null authenticator
64 | */
65 | @Test
66 | public void testClusterNodeWithoutConnectionAuthenticator() {
67 | String node = "node1";
68 | Cluster cluster = new Cluster(node, 5555, false);
69 | assertNull("Connection authentication should be null",cluster.getConnectionConfig().getConnectionAuthenticator());
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/test/java/org/scale7/cassandra/pelops/CompositeTypeIntegrationTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | /*
26 | * To change this template, choose Tools | Templates
27 | * and open the template in the editor.
28 | */
29 | package org.scale7.cassandra.pelops;
30 |
31 | import static org.junit.Assert.assertArrayEquals;
32 | import static org.junit.Assert.assertEquals;
33 | import static org.junit.Assert.assertNotNull;
34 | import static org.junit.Assert.fail;
35 |
36 | import java.util.ArrayList;
37 | import java.util.Arrays;
38 | import java.util.List;
39 |
40 | import org.apache.cassandra.thrift.CfDef;
41 | import org.apache.cassandra.thrift.Column;
42 | import org.apache.cassandra.thrift.ConsistencyLevel;
43 | import org.junit.BeforeClass;
44 | import org.junit.Test;
45 | import org.scale7.cassandra.pelops.support.AbstractIntegrationTest;
46 | import org.scale7.cassandra.pelops.types.CompositeType;
47 |
48 | /**
49 | *
50 | * @author Ali Serghini
51 | */
52 | public class CompositeTypeIntegrationTest extends AbstractIntegrationTest {
53 |
54 | private static final String CF = "CF_CompositeKey";
55 | private static final List KEYS = new ArrayList(12);
56 |
57 | public CompositeTypeIntegrationTest() {
58 | }
59 |
60 | @BeforeClass
61 | public static void setup() throws Exception {
62 | setup(Arrays.asList(new CfDef(KEYSPACE, CF)
63 | .setComparator_type("CompositeType(LongType,UTF8Type)")
64 | .setKey_validation_class("LongType")));
65 |
66 | final CompositeType.Builder builder = CompositeType.Builder.newBuilder(2);
67 | KEYS.add(builder.addLong(1l).addUTF8("a").build());
68 | builder.clear();
69 | KEYS.add(builder.addLong(1l).addUTF8("b").build());
70 | builder.clear();
71 | KEYS.add(builder.addLong(1l).addUTF8("c").build());
72 | builder.clear();
73 | KEYS.add(builder.addLong(2l).addUTF8("a").build());
74 | builder.clear();
75 | KEYS.add(builder.addLong(2l).addUTF8("b").build());
76 | builder.clear();
77 | KEYS.add(builder.addLong(2l).addUTF8("c").build());
78 | builder.clear();
79 | KEYS.add(builder.addLong(3l).addUTF8("a").build());
80 | builder.clear();
81 | KEYS.add(builder.addLong(3l).addUTF8("b").build());
82 | builder.clear();
83 | KEYS.add(builder.addLong(3l).addUTF8("c").build());
84 | builder.clear();
85 | KEYS.add(builder.addLong(4l).addUTF8("a").build());
86 | builder.clear();
87 | KEYS.add(builder.addLong(4l).addUTF8("b").build());
88 | builder.clear();
89 | KEYS.add(builder.addLong(4l).addUTF8("c").build());
90 | builder.clear();
91 | }
92 |
93 | @Override
94 | public void prepareData() throws Exception {
95 | final Mutator mutator = createMutator();
96 | final List columns = new ArrayList(KEYS.size());
97 | for (Bytes bytes : KEYS) {
98 | columns.add(mutator.newColumn(bytes));
99 | }
100 |
101 | mutator.writeColumns(CF, Bytes.fromLong(1l), columns);
102 | mutator.execute(ConsistencyLevel.ONE);
103 | }
104 |
105 | @Test
106 | public void testAdd() {
107 | // data is setup in the prepareData method...
108 | int count = createSelector().getColumnCount(CF, Bytes.fromLong(1l), ConsistencyLevel.ONE);
109 | assertEquals(KEYS.size(), count);
110 | }
111 |
112 | @Test
113 | public void testGet() {
114 | List columns = createSelector().getColumnsFromRow(CF, Bytes.fromLong(1l), false, ConsistencyLevel.ONE);
115 | assertNotNull(columns);
116 | assertEquals(columns.size(), KEYS.size());
117 |
118 | List bytes = null;
119 | long first = 1l;
120 | String second = "a";
121 | for (Column column : columns) {
122 | bytes = CompositeType.parse(column.getName());
123 | assertArrayEquals(bytes.get(0), Bytes.fromLong(first).toByteArray());
124 | assertArrayEquals(bytes.get(1), Bytes.fromUTF8(second).toByteArray());
125 |
126 | if (Arrays.equals(bytes.get(1), Bytes.fromUTF8("c").toByteArray())) {
127 | first++;
128 | second = "a";
129 | } else if (Arrays.equals(bytes.get(1), Bytes.fromUTF8("a").toByteArray())) {
130 | second = "b";
131 | } else if (Arrays.equals(bytes.get(1), Bytes.fromUTF8("b").toByteArray())) {
132 | second = "c";
133 | } else {
134 | fail();
135 | }
136 | }
137 | }
138 |
139 | @Test
140 | public void testSlice() {
141 | final CompositeType.Builder builder = CompositeType.Builder.newBuilder(2);
142 | builder.addLong(3l).addUTF8("b");
143 |
144 | List bytes = createSelector().getPageOfColumnNamesFromRow(CF, Bytes.fromLong(1l), builder.build(), false, 20, ConsistencyLevel.ONE);
145 | assertNotNull(bytes);
146 | assertEquals(4, bytes.size());
147 |
148 | for (Bytes b : bytes) {
149 | List bb = CompositeType.parse(b);
150 | System.out.println("=> first: " + Bytes.fromByteArray(bb.get(0)).toLong() + " second: " + Bytes.fromByteArray(bb.get(1)).toUTF8());
151 | }
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/src/test/java/org/scale7/cassandra/pelops/SimpleConnectionAuthenticatorUnitTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2011 Dominic Williams, Daniel Washusen and contributors.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.scale7.cassandra.pelops;
26 |
27 | import static org.junit.Assert.assertEquals;
28 |
29 | import org.junit.Test;
30 |
31 | /**
32 | * Tests the {@link Bytes} class.
33 | */
34 | public class SimpleConnectionAuthenticatorUnitTest {
35 | @Test
36 | public void testEquals() {
37 | assertEquals("Username key changed in Cassandra JAR", SimpleConnectionAuthenticator.USERNAME_KEY, SimpleConnectionAuthenticator.USERNAME_KEY);
38 | assertEquals("Password key changed in Cassandra JAR", SimpleConnectionAuthenticator.PASSWORD_KEY, SimpleConnectionAuthenticator.PASSWORD_KEY);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/test/java/org/scale7/cassandra/pelops/UuidHelperUnitTest.java:
--------------------------------------------------------------------------------
1 | package org.scale7.cassandra.pelops;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.scale7.cassandra.pelops.UuidHelper.millisFromTimeUuid;
5 | import static org.scale7.cassandra.pelops.UuidHelper.nonUniqueTimeUuidForDate;
6 |
7 | import java.util.UUID;
8 |
9 | import org.junit.Test;
10 |
11 | public class UuidHelperUnitTest {
12 | @Test
13 | public void testTimeUuidForDate() {
14 | long millisSource = System.currentTimeMillis();
15 |
16 | UUID uuid = nonUniqueTimeUuidForDate(millisSource);
17 |
18 | long millisFromUuid = millisFromTimeUuid(uuid);
19 |
20 | assertEquals("Timestamp was not equal to source", millisSource, millisFromUuid);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/test/java/org/scale7/cassandra/pelops/exceptions/ExceptionTranslatorUnitTest.java:
--------------------------------------------------------------------------------
1 | package org.scale7.cassandra.pelops.exceptions;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertTrue;
5 |
6 | import java.net.SocketException;
7 |
8 | import org.junit.Test;
9 |
10 | /**
11 | * Tests the {@link IExceptionTranslator.ExceptionTranslator} class.
12 | */
13 | public class ExceptionTranslatorUnitTest {
14 | private IExceptionTranslator.ExceptionTranslator translator = new IExceptionTranslator.ExceptionTranslator();
15 |
16 | @Test
17 | public void testTranslateNotFoundException() {
18 | PelopsException pelopsException = translator.translate(new org.apache.cassandra.thrift.NotFoundException());
19 | assertEquals("Translation failed", NotFoundException.class, pelopsException.getClass());
20 | }
21 |
22 | @Test
23 | public void testTranslateInvalidRequestException() {
24 | PelopsException pelopsException = translator.translate(new org.apache.cassandra.thrift.InvalidRequestException());
25 | assertEquals("Translation failed", InvalidRequestException.class, pelopsException.getClass());
26 | }
27 |
28 | @Test
29 | public void testTranslateApplicationException() {
30 | PelopsException pelopsException = translator.translate(new org.apache.thrift.TApplicationException());
31 | assertEquals("Translation failed", ApplicationException.class, pelopsException.getClass());
32 | }
33 |
34 | @Test
35 | public void testTranslateAuthenticationException() {
36 | PelopsException pelopsException = translator.translate(new org.apache.cassandra.thrift.AuthenticationException());
37 | assertEquals("Translation failed", AuthenticationException.class, pelopsException.getClass());
38 | }
39 |
40 | @Test
41 | public void testTranslateAuthorizationException() {
42 | PelopsException pelopsException = translator.translate(new org.apache.cassandra.thrift.AuthorizationException());
43 | assertEquals("Translation failed", AuthorizationException.class, pelopsException.getClass());
44 | }
45 |
46 | @Test
47 | public void testTranslateTimedOutException() {
48 | PelopsException pelopsException = translator.translate(new org.apache.cassandra.thrift.TimedOutException());
49 | assertEquals("Translation failed", TimedOutException.class, pelopsException.getClass());
50 | }
51 |
52 | @Test
53 | public void testTranslateTransportException() {
54 | PelopsException pelopsException = translator.translate(new org.apache.thrift.transport.TTransportException());
55 | assertEquals("Translation failed", TransportException.class, pelopsException.getClass());
56 | }
57 |
58 | @Test
59 | public void testTranslateProtocolException() {
60 | PelopsException pelopsException = translator.translate(new org.apache.thrift.protocol.TProtocolException());
61 | assertEquals("Translation failed", ProtocolException.class, pelopsException.getClass());
62 | }
63 |
64 | @Test
65 | public void testTranslateUnavailableException() {
66 | PelopsException pelopsException = translator.translate(new org.apache.cassandra.thrift.UnavailableException());
67 | assertEquals("Translation failed", UnavailableException.class, pelopsException.getClass());
68 | }
69 |
70 | @Test
71 | public void testTranslatePelopsException() {
72 | PelopsException exception = new PelopsException();
73 | PelopsException pelopsException = translator.translate(exception);
74 | assertTrue("Translation failed", exception == pelopsException);
75 | }
76 |
77 | @Test
78 | public void testTranslateOtherException() {
79 | PelopsException pelopsException = translator.translate(new SocketException());
80 | assertEquals("Translation failed", PelopsException.class, pelopsException.getClass());
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/test/java/org/scale7/cassandra/pelops/pool/LeastLoadedNodeSelectionStrategyUnitTest.java:
--------------------------------------------------------------------------------
1 | package org.scale7.cassandra.pelops.pool;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertNotNull;
5 | import static org.junit.Assert.assertNull;
6 |
7 | import java.util.Arrays;
8 | import java.util.HashSet;
9 | import java.util.List;
10 | import java.util.Set;
11 |
12 | import org.junit.Test;
13 | import org.mockito.Mockito;
14 | import org.mockito.invocation.InvocationOnMock;
15 | import org.mockito.stubbing.Answer;
16 |
17 | import com.google.common.collect.Sets;
18 |
19 | /**
20 | * Tests the {@link LeastLoadedNodeSelectionStrategy} class.
21 | */
22 | public class LeastLoadedNodeSelectionStrategyUnitTest {
23 | /**
24 | * Test to verify that if all nodes are are suspended that null is returned.
25 | */
26 | @Test
27 | public void testAllNodesSuspended() {
28 | Set nodeAddresses = new HashSet(Arrays.asList("node1", "node2", "node3"));
29 | CommonsBackedPool pool = Mockito.mock(CommonsBackedPool.class);
30 |
31 | // setup each pooled node to report that it's suspended
32 | for (String nodeAddress : nodeAddresses) {
33 | mockPoolMethods(pool, nodeAddress, new PooledNode(pool, nodeAddress) {
34 | @Override
35 | public boolean isSuspended() {
36 | return true;
37 | }
38 | });
39 | }
40 |
41 | LeastLoadedNodeSelectionStrategy strategy = new LeastLoadedNodeSelectionStrategy();
42 |
43 | PooledNode node = strategy.select(pool, nodeAddresses, null);
44 |
45 | assertNull("No nodes should have been returned", node);
46 | }
47 |
48 | /**
49 | * Test to verify that if all but one of the nodes are suspended that that node is returned.
50 | */
51 | @Test
52 | public void testOnlyOneCandidateNode() {
53 | Set nodeAddresses = new HashSet(Arrays.asList("node1", "node2", "node3"));
54 | CommonsBackedPool pool = Mockito.mock(CommonsBackedPool.class);
55 |
56 | // setup each pooled node to report that it's suspended
57 | for (String nodeAddress : nodeAddresses) {
58 | mockPoolMethods(pool, nodeAddress, new PooledNode(pool, nodeAddress) {
59 | @Override
60 | public boolean isSuspended() {
61 | return true;
62 | }
63 | });
64 | }
65 |
66 | // setup one node to be good
67 | final String goodNodeAddress = "node4";
68 | nodeAddresses.add(goodNodeAddress);
69 | mockPoolMethods(pool, goodNodeAddress, new PooledNode(pool, goodNodeAddress) {
70 | @Override
71 | public boolean isSuspended() {
72 | return false;
73 | }
74 |
75 | @Override
76 | public int getNumActive() {
77 | return 1;
78 | }
79 |
80 | @Override
81 | public int getConnectionsCorrupted() {
82 | return 0;
83 | }
84 | });
85 |
86 | LeastLoadedNodeSelectionStrategy strategy = new LeastLoadedNodeSelectionStrategy();
87 |
88 | PooledNode node = strategy.select(pool, nodeAddresses, null);
89 |
90 | assertNotNull("No nodes were returned from the pool", node);
91 | assertEquals("Wrong node returned from the pool", goodNodeAddress, node.getAddress());
92 | }
93 |
94 | /**
95 | * Test to verify that the node with the least active connections is selected.
96 | */
97 | @Test
98 | public void testLeastLoadedNodeSelected() {
99 | String leastLoadedNodeAddress = "node1";
100 | List nodeAddresses = Arrays.asList(leastLoadedNodeAddress, "node2", "node3", "node4", "node5");
101 | CommonsBackedPool pool = Mockito.mock(CommonsBackedPool.class);
102 |
103 | // setup each pooled node to report it's number of active connections
104 | for (int i = 0; i < nodeAddresses.size(); i++) {
105 | final int numActive = i;
106 | mockPoolMethods(pool, nodeAddresses.get(i), new PooledNode(pool, nodeAddresses.get(i)) {
107 | @Override
108 | public boolean isSuspended() {
109 | return false;
110 | }
111 |
112 | @Override
113 | public int getNumActive() {
114 | return numActive;
115 | }
116 |
117 | @Override
118 | public int getConnectionsCorrupted() {
119 | return 0;
120 | }
121 | });
122 | }
123 |
124 | LeastLoadedNodeSelectionStrategy strategy = new LeastLoadedNodeSelectionStrategy();
125 |
126 | PooledNode node = strategy.select(pool, new HashSet(nodeAddresses), null);
127 |
128 | assertNotNull("No nodes were returned from the pool", node);
129 | assertEquals("Wrong node returned from the pool", leastLoadedNodeAddress, node.getAddress());
130 | }
131 |
132 | /**
133 | * Test to verify that when all nodes have an equal number of active and borrowed nodes then the node with the least corrupted
134 | * connections is selected.
135 | */
136 | @Test
137 | public void testNodesEqualThenLeastCorruptedSelected() {
138 | String leastLoadedNodeAddress = "node5";
139 | final List nodeAddresses = Arrays.asList("node1", "node2", "node3", "node4", leastLoadedNodeAddress);
140 | CommonsBackedPool pool = Mockito.mock(CommonsBackedPool.class);
141 |
142 | // setup each pooled node to report it's number of active connections
143 | for (int i = 0; i < nodeAddresses.size(); i++) {
144 | final int numCorrupted = i;
145 | mockPoolMethods(pool, nodeAddresses.get(i), new PooledNode(pool, nodeAddresses.get(i)) {
146 | @Override
147 | public boolean isSuspended() {
148 | return false;
149 | }
150 |
151 | @Override
152 | public int getNumActive() {
153 | return 0;
154 | }
155 |
156 | @Override
157 | public int getConnectionsBorrowedTotal() {
158 | return 0;
159 | }
160 |
161 | @Override
162 | public int getConnectionsCorrupted() {
163 | return nodeAddresses.size() - numCorrupted;
164 | }
165 | });
166 | }
167 |
168 | LeastLoadedNodeSelectionStrategy strategy = new LeastLoadedNodeSelectionStrategy();
169 |
170 | PooledNode node = strategy.select(pool, new HashSet(nodeAddresses), null);
171 |
172 | assertNotNull("No nodes were returned from the pool", node);
173 | assertEquals("Wrong node returned from the pool", leastLoadedNodeAddress, node.getAddress());
174 | }
175 |
176 | /**
177 | * Test to verify that when all nodes have an equal number of active and borrowed nodes then the node with the least corrupted
178 | * connections is selected.
179 | */
180 | @Test
181 | public void testNodesEqualThenLeastBorrowedSelected() {
182 | String leastLoadedNodeAddress = "node5";
183 | final List nodeAddresses = Arrays.asList("node1", "node2", "node3", "node4", leastLoadedNodeAddress);
184 | CommonsBackedPool pool = Mockito.mock(CommonsBackedPool.class);
185 |
186 | // setup each pooled node to report it's number of active connections
187 | for (int i = 0; i < nodeAddresses.size(); i++) {
188 | final int numCorrupted = i;
189 | mockPoolMethods(pool, nodeAddresses.get(i), new PooledNode(pool, nodeAddresses.get(i)) {
190 | @Override
191 | public boolean isSuspended() {
192 | return false;
193 | }
194 |
195 | @Override
196 | public int getNumActive() {
197 | return 0;
198 | }
199 |
200 | @Override
201 | public int getConnectionsBorrowedTotal() {
202 | return nodeAddresses.size() - numCorrupted;
203 | }
204 |
205 | @Override
206 | public int getConnectionsCorrupted() {
207 | return 0;
208 | }
209 | });
210 | }
211 |
212 | LeastLoadedNodeSelectionStrategy strategy = new LeastLoadedNodeSelectionStrategy();
213 |
214 | PooledNode node = strategy.select(pool, new HashSet(nodeAddresses), null);
215 |
216 | assertNotNull("No nodes were returned from the pool", node);
217 | assertEquals("Wrong node returned from the pool", leastLoadedNodeAddress, node.getAddress());
218 | }
219 |
220 | /**
221 | * Test to verify that the node with the least active connections is skipped because of the notNodeHint.
222 | */
223 | @Test
224 | public void testAvoidNodesHint() {
225 | String avoidNode = "node1";
226 | String selectedNodeAddress = "node2";
227 | List nodeAddresses = Arrays.asList(avoidNode, selectedNodeAddress, "node3", "node4", "node5");
228 | CommonsBackedPool pool = Mockito.mock(CommonsBackedPool.class);
229 |
230 | // setup each pooled node to report it's number of active connections
231 | for (int i = 0; i < nodeAddresses.size(); i++) {
232 | final int numActive = i;
233 | mockPoolMethods(pool, nodeAddresses.get(i), new PooledNode(pool, nodeAddresses.get(i)) {
234 | @Override
235 | public boolean isSuspended() {
236 | return false;
237 | }
238 |
239 | @Override
240 | public int getNumActive() {
241 | return numActive;
242 | }
243 |
244 | @Override
245 | public int getConnectionsCorrupted() {
246 | return 0;
247 | }
248 | });
249 | }
250 |
251 | LeastLoadedNodeSelectionStrategy strategy = new LeastLoadedNodeSelectionStrategy();
252 |
253 | PooledNode node = strategy.select(pool, new HashSet(nodeAddresses), Sets.newHashSet(avoidNode));
254 |
255 | assertNotNull("No nodes were returned from the pool", node);
256 | assertEquals("Wrong node returned from the pool", selectedNodeAddress, node.getAddress());
257 | }
258 |
259 | /**
260 | * Test to verify that the node with the least active connections is skipped because of the notNodeHint.
261 | */
262 | @Test
263 | public void testAvoidNodesHintMultiple() {
264 | String avoidNode1 = "node1";
265 | String avoidNode2 = "node2";
266 | String selectedNodeAddress = "node3";
267 | List nodeAddresses = Arrays.asList(avoidNode1, avoidNode2, selectedNodeAddress, "node4", "node5");
268 | CommonsBackedPool pool = Mockito.mock(CommonsBackedPool.class);
269 |
270 | // setup each pooled node to report it's number of active connections
271 | for (int i = 0; i < nodeAddresses.size(); i++) {
272 | final int numActive = i;
273 | mockPoolMethods(pool, nodeAddresses.get(i), new PooledNode(pool, nodeAddresses.get(i)) {
274 | @Override
275 | public boolean isSuspended() {
276 | return false;
277 | }
278 |
279 | @Override
280 | public int getNumActive() {
281 | return numActive;
282 | }
283 |
284 | @Override
285 | public int getConnectionsCorrupted() {
286 | return 0;
287 | }
288 | });
289 | }
290 |
291 | LeastLoadedNodeSelectionStrategy strategy = new LeastLoadedNodeSelectionStrategy();
292 |
293 | PooledNode node = strategy.select(pool, new HashSet(nodeAddresses), Sets.newHashSet(avoidNode1, avoidNode2));
294 |
295 | assertNotNull("No nodes were returned from the pool", node);
296 | assertEquals("Wrong node returned from the pool", selectedNodeAddress, node.getAddress());
297 | }
298 |
299 | private void mockPoolMethods(CommonsBackedPool pool, final String nodeAddress, final PooledNode pooledNode) {
300 | Mockito.when(pool.getPooledNode(nodeAddress)).thenAnswer(new Answer() {
301 | @Override
302 | public PooledNode answer(InvocationOnMock invocation) throws Throwable {
303 | return pooledNode;
304 | }
305 | });
306 | }
307 | }
308 |
--------------------------------------------------------------------------------
/src/test/java/org/scale7/cassandra/pelops/spring/CommonsBackedPoolFactoryBeanIntegrationTest.java:
--------------------------------------------------------------------------------
1 | package org.scale7.cassandra.pelops.spring;
2 |
3 | import static org.junit.Assert.assertNotNull;
4 | import static org.junit.Assert.assertNull;
5 | import static org.junit.Assert.assertTrue;
6 | import static org.junit.Assert.fail;
7 |
8 | import java.util.ArrayList;
9 |
10 | import org.apache.cassandra.thrift.CfDef;
11 | import org.junit.BeforeClass;
12 | import org.junit.Test;
13 | import org.scale7.cassandra.pelops.OperandPolicy;
14 | import org.scale7.cassandra.pelops.pool.CommonsBackedPool;
15 | import org.scale7.cassandra.pelops.pool.LeastLoadedNodeSelectionStrategy;
16 | import org.scale7.cassandra.pelops.pool.NoOpConnectionValidator;
17 | import org.scale7.cassandra.pelops.pool.NoOpNodeSuspensionStrategy;
18 | import org.scale7.cassandra.pelops.support.AbstractIntegrationTest;
19 |
20 | /**
21 | * Tests the {@link CommonsBackedPoolFactoryBean} class.
22 | *
23 | * Note: it uses the debugging pool option to avoid attempting to connect to a Cassandra instance.
24 | */
25 | public class CommonsBackedPoolFactoryBeanIntegrationTest extends AbstractIntegrationTest {
26 | @BeforeClass
27 | public static void setup() throws Exception {
28 | setup(new ArrayList());
29 | }
30 |
31 | /**
32 | * Tests the factory bean works as expected when no operand or pool policy are specified.
33 | * @throws Exception if an error occurs
34 | */
35 | @Test
36 | public void testAfterPropertiesSetSimpleUseCase() throws Exception {
37 | CommonsBackedPoolFactoryBean factoryBean = new CommonsBackedPoolFactoryBean();
38 | factoryBean.setCluster(AbstractIntegrationTest.cluster);
39 | factoryBean.setKeyspace(AbstractIntegrationTest.KEYSPACE);
40 |
41 | assertNull("The factory should not have created the pool at this point", factoryBean.getObject());
42 |
43 | try {
44 | factoryBean.afterPropertiesSet();
45 |
46 | CommonsBackedPool pool = (CommonsBackedPool) factoryBean.getObject();
47 | assertNotNull("The factory didn't initialize the pool", pool);
48 | assertNotNull("The factory didn't initialize a default operand policy instance", pool.getOperandPolicy());
49 | assertNotNull("The factory didn't initialize a default pool config instance", pool.getPolicy());
50 | assertNotNull("The factory didn't initialize a default node selection policy instance", pool.getNodeSelectionStrategy());
51 | assertNotNull("The factory didn't initialize a default node suspension policy instance", pool.getNodeSuspensionStrategy());
52 | assertNotNull("The factory didn't initialize a default connection validator policy instance", pool.getConnectionValidator());
53 | } finally {
54 | factoryBean.destroy();
55 | }
56 | }
57 |
58 | /**
59 | * Tests the factory bean works as expected when operand or pool policy instances are provided.
60 | * @throws Exception if an error occurs
61 | */
62 | @Test
63 | public void testAfterProperties() throws Exception {
64 | OperandPolicy operandPolicy = new OperandPolicy();
65 | CommonsBackedPool.Policy policy = new CommonsBackedPool.Policy();
66 | LeastLoadedNodeSelectionStrategy nodeSelectionStrategy = new LeastLoadedNodeSelectionStrategy();
67 | NoOpNodeSuspensionStrategy nodeSuspensionStrategy = new NoOpNodeSuspensionStrategy();
68 | NoOpConnectionValidator connectionValidator = new NoOpConnectionValidator();
69 |
70 | CommonsBackedPoolFactoryBean factoryBean = new CommonsBackedPoolFactoryBean();
71 | factoryBean.setCluster(AbstractIntegrationTest.cluster);
72 | factoryBean.setKeyspace(AbstractIntegrationTest.KEYSPACE);
73 | factoryBean.setPolicy(policy);
74 | factoryBean.setOperandPolicy(operandPolicy);
75 | factoryBean.setNodeSelectionStrategy(nodeSelectionStrategy);
76 | factoryBean.setNodeSuspensionStrategy(nodeSuspensionStrategy);
77 | factoryBean.setConnectionValidator(connectionValidator);
78 |
79 | assertNull("The factory should not have created the pool at this point", factoryBean.getObject());
80 |
81 | try {
82 | factoryBean.afterPropertiesSet();
83 |
84 | CommonsBackedPool pool = (CommonsBackedPool) factoryBean.getObject();
85 | assertNotNull("The factory didn't initialize the pool", pool);
86 | assertTrue("The factory didn't use the provided operand policy instance", operandPolicy == pool.getOperandPolicy());
87 | assertTrue("The factory didn't use the provided config instance", policy == pool.getPolicy());
88 | assertTrue("The factory didn't use the provided config instance", cluster == pool.getCluster());
89 | assertTrue("The factory didn't use the provided node selection instance", nodeSelectionStrategy == pool.getNodeSelectionStrategy());
90 | assertTrue("The factory didn't use the provided node suspension instance", nodeSuspensionStrategy == pool.getNodeSuspensionStrategy());
91 | assertTrue("The factory didn't use the provided connection validator instance", connectionValidator == pool.getConnectionValidator());
92 | } finally {
93 | factoryBean.destroy();
94 | }
95 | }
96 |
97 | /**
98 | * Test to ensure that the required keyspace property is validated.
99 | * @throws Exception if an error occurs
100 | */
101 | @Test
102 | public void testValidationKeyspace() throws Exception {
103 | CommonsBackedPoolFactoryBean factoryBean = new CommonsBackedPoolFactoryBean();
104 | factoryBean.setCluster(AbstractIntegrationTest.cluster);
105 | try {
106 | factoryBean.afterPropertiesSet();
107 | fail("The factory bean should have failed with a missing keyspace property");
108 | } catch (IllegalArgumentException e) {
109 | // expected
110 | }
111 | }
112 |
113 | /**
114 | * Test to ensure that the required clsuter property is validated.
115 | * @throws Exception if an error occurs
116 | */
117 | @Test
118 | public void testValidationCluster() throws Exception {
119 | CommonsBackedPoolFactoryBean factoryBean = new CommonsBackedPoolFactoryBean();
120 | factoryBean.setKeyspace("keyspace");
121 | try {
122 | factoryBean.afterPropertiesSet();
123 | fail("The factory bean should have failed with a missing cluster property");
124 | } catch (IllegalArgumentException e) {
125 | // expected
126 | }
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/src/test/java/org/scale7/cassandra/pelops/support/AbstractIntegrationTest.java:
--------------------------------------------------------------------------------
1 | package org.scale7.cassandra.pelops.support;
2 |
3 | import java.util.ArrayList;
4 | import java.util.HashMap;
5 | import java.util.List;
6 | import java.util.Map;
7 |
8 | import org.apache.cassandra.thrift.CfDef;
9 | import org.apache.cassandra.thrift.KsDef;
10 | import org.junit.Before;
11 | import org.scale7.cassandra.pelops.Cluster;
12 | import org.scale7.cassandra.pelops.ColumnFamilyManager;
13 | import org.scale7.cassandra.pelops.KeyspaceManager;
14 | import org.scale7.cassandra.pelops.Mutator;
15 | import org.scale7.cassandra.pelops.OperandPolicy;
16 | import org.scale7.cassandra.pelops.Selector;
17 | import org.scale7.cassandra.pelops.pool.DebuggingPool;
18 | import org.scale7.cassandra.pelops.pool.IThriftPool;
19 | import org.scale7.portability.SystemProxy;
20 | import org.slf4j.Logger;
21 |
22 | /**
23 | * Abstract integration test class which runs its own embedded cassandra server.
24 | */
25 | public abstract class AbstractIntegrationTest {
26 |
27 | protected final Logger logger = SystemProxy.getLoggerFromFactory(this
28 | .getClass());
29 |
30 | public static final String RPC_LISTEN_ADDRESS = "localhost";
31 |
32 | public static final int RPC_PORT = 19160;
33 |
34 | public static final String KEYSPACE = "PelopsTesting";
35 |
36 | private static EmbeddedCassandraServer cassandraServer;
37 |
38 | public static Cluster cluster = new Cluster(RPC_LISTEN_ADDRESS, RPC_PORT);
39 |
40 | private static KeyspaceManager keyspaceManager;
41 |
42 | private static ColumnFamilyManager columnFamilyManager;
43 |
44 | private static List colFamilyDefs;
45 |
46 | private IThriftPool pool = new DebuggingPool(cluster, KEYSPACE, new OperandPolicy());
47 |
48 | public KeyspaceManager getKeyspaceManager() {
49 | return keyspaceManager;
50 | }
51 |
52 | public ColumnFamilyManager getColumnFamilyManager() {
53 | return columnFamilyManager;
54 | }
55 |
56 | protected Cluster getCluster() {
57 | return cluster;
58 | }
59 |
60 | protected IThriftPool getPool() {
61 | return pool;
62 | }
63 |
64 | /**
65 | * Starts embedded cassandra server.
66 | *
67 | * @throws Exception
68 | * if an error occurs
69 | */
70 | public static void setup(List columnDefinitions) throws Exception {
71 | if (cassandraServer == null) {
72 | cassandraServer = new EmbeddedCassandraServer();
73 | cassandraServer.start();
74 |
75 | // wait until cassandra server starts up. could wait less time, but
76 | // 2 seconds to be sure.
77 | Thread.sleep(2000);
78 | }
79 |
80 | colFamilyDefs = columnDefinitions;
81 |
82 | keyspaceManager = new KeyspaceManager(cluster);
83 | columnFamilyManager = new ColumnFamilyManager(cluster, KEYSPACE);
84 |
85 | List keyspaces = keyspaceManager.getKeyspaceNames();
86 | for (KsDef ksDef : keyspaces)
87 | if (ksDef.name.equals(KEYSPACE)) {
88 | keyspaceManager.dropKeyspace(KEYSPACE);
89 | }
90 |
91 | KsDef keyspaceDefinition = new KsDef(KEYSPACE, KeyspaceManager.KSDEF_STRATEGY_SIMPLE, new ArrayList());
92 | Map strategyOptions = new HashMap();
93 | strategyOptions.put("replication_factor", "1");
94 | keyspaceDefinition.setStrategy_options(strategyOptions);
95 |
96 | for (CfDef colFamilyDef : colFamilyDefs) {
97 | keyspaceDefinition.addToCf_defs(colFamilyDef);
98 | }
99 |
100 | keyspaceManager.addKeyspace(keyspaceDefinition);
101 | }
102 |
103 | /**
104 | * Database prepare before test.
105 | *
106 | * @throws Exception
107 | * if an error occurs
108 | */
109 | @Before
110 | public void setupTest() throws Exception {
111 | truncate();
112 | prepareData();
113 | }
114 |
115 | /**
116 | * Data prepare. Its purpose is to be overloaded from test class.
117 | *
118 | * @throws Exception
119 | * if an error occurs
120 | */
121 | public void prepareData() throws Exception {
122 | }
123 |
124 | /**
125 | * Truncate all column families.
126 | */
127 | public void truncate() {
128 | for (CfDef colFamilyDef : colFamilyDefs) {
129 | try {
130 | columnFamilyManager
131 | .truncateColumnFamily(colFamilyDef.getName());
132 | } catch (Exception e) {
133 | throw new IllegalStateException(
134 | "Failed to truncate column family "
135 | + colFamilyDef.getName(), e);
136 | }
137 | }
138 | }
139 |
140 | /**
141 | * @return new mutator instance
142 | */
143 | public Mutator createMutator() {
144 | return pool.createMutator();
145 | }
146 |
147 | /**
148 | * @return new selector instance
149 | */
150 | public Selector createSelector() {
151 | return pool.createSelector();
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/src/test/java/org/scale7/cassandra/pelops/support/EmbeddedCassandraServer.java:
--------------------------------------------------------------------------------
1 | package org.scale7.cassandra.pelops.support;
2 |
3 | import java.io.File;
4 |
5 | import org.apache.cassandra.io.util.FileUtils;
6 | import org.apache.cassandra.service.CassandraDaemon;
7 | import org.scale7.portability.SystemProxy;
8 | import org.slf4j.Logger;
9 |
10 | /**
11 | * This class starts and stops embedded Cassandra server.
12 | *
13 | * For instance of server is created temporary directory (in target/tmp) for data files and configuration.
14 | *
15 | * @author Alois Belaska
16 | */
17 | public class EmbeddedCassandraServer {
18 |
19 | private final Logger logger = SystemProxy.getLoggerFromFactory(EmbeddedCassandraServer.class);
20 |
21 | private String baseDirectory = "target/tmp";
22 |
23 | private CassandraDaemon cassandraDaemon;
24 |
25 | private Thread cassandraThread;
26 |
27 | /**
28 | * @return temporary base directory of running cassandra instance
29 | */
30 | public String getBaseDirectory() {
31 | return baseDirectory;
32 | }
33 |
34 | /**
35 | * starts embedded Cassandra server.
36 | *
37 | * @throws Exception
38 | * if an error occurs
39 | */
40 | public void start() throws Exception {
41 | try {
42 | cleanupDirectoriesFailover();
43 |
44 | FileUtils.createDirectory(baseDirectory);
45 |
46 | System.setProperty("log4j.configuration", "file:target/test-classes/log4j.properties");
47 | System.setProperty("cassandra.config", "file:target/test-classes/cassandra.yaml");
48 |
49 | cassandraDaemon = new CassandraDaemon();
50 | cassandraDaemon.init(null);
51 | cassandraThread = new Thread(new Runnable() {
52 | public void run() {
53 | try {
54 | cassandraDaemon.start();
55 | } catch (Exception e) {
56 | logger.error("Embedded casandra server run failed", e);
57 | }
58 | }
59 | });
60 | cassandraThread.setDaemon(true);
61 | cassandraThread.start();
62 | } catch (Exception e) {
63 | logger.error("Embedded casandra server start failed", e);
64 |
65 | // cleanup
66 | stop();
67 | }
68 | }
69 |
70 | /**
71 | * Stops embedded Cassandra server.
72 | *
73 | * @throws Exception
74 | * if an error occurs
75 | */
76 | public void stop() throws Exception {
77 | if (cassandraThread != null) {
78 | cassandraDaemon.stop();
79 | cassandraDaemon.destroy();
80 | cassandraThread.interrupt();
81 | cassandraThread = null;
82 | }
83 |
84 | cleanupDirectoriesFailover();
85 | }
86 |
87 | /**
88 | * Cleans up cassandra's temporary base directory.
89 | *
90 | * In case o failure waits for 250 msecs and then tries it again, 3 times totally.
91 | */
92 | public void cleanupDirectoriesFailover() {
93 | int tries = 3;
94 | while (tries-- > 0) {
95 | try {
96 | cleanupDirectories();
97 | break;
98 | } catch (Exception e) {
99 | // ignore exception
100 | try {
101 | Thread.sleep(250);
102 | } catch (InterruptedException e1) {
103 | // ignore exception
104 | }
105 | }
106 | }
107 | }
108 |
109 | /**
110 | * Cleans up cassandra's temporary base directory.
111 | *
112 | * @throws Exception
113 | * if an error occurs
114 | */
115 | public void cleanupDirectories() throws Exception {
116 | File dirFile = new File(baseDirectory);
117 | if (dirFile.exists()) {
118 | FileUtils.deleteRecursive(dirFile);
119 | }
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/src/test/java/org/scale7/cassandra/pelops/types/CompositeTypeTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * To change this template, choose Tools | Templates
3 | * and open the template in the editor.
4 | */
5 | package org.scale7.cassandra.pelops.types;
6 |
7 | import static org.junit.Assert.assertEquals;
8 | import static org.junit.Assert.assertNotNull;
9 | import static org.junit.Assert.assertTrue;
10 |
11 | import java.nio.ByteBuffer;
12 | import java.util.Arrays;
13 | import java.util.List;
14 | import java.util.UUID;
15 |
16 | import org.junit.After;
17 | import org.junit.AfterClass;
18 | import org.junit.Before;
19 | import org.junit.BeforeClass;
20 | import org.junit.Test;
21 | import org.scale7.cassandra.pelops.Bytes;
22 |
23 | /**
24 | *
25 | * @author Ali Serghini
26 | */
27 | public class CompositeTypeTest {
28 |
29 | public CompositeTypeTest() {
30 | }
31 |
32 | @BeforeClass
33 | public static void setUpClass() throws Exception {
34 | }
35 |
36 | @AfterClass
37 | public static void tearDownClass() throws Exception {
38 | }
39 |
40 | @Before
41 | public void setUp() {
42 | }
43 |
44 | @After
45 | public void tearDown() {
46 | }
47 |
48 | @Test
49 | public void test() {
50 | final CompositeType.Builder builder = CompositeType.Builder.newBuilder(13);
51 |
52 | builder.addBoolean(true);
53 | builder.addByte((byte) 5);
54 | builder.addByteArray("byte[] test".getBytes());
55 | builder.addByteBuffer(ByteBuffer.wrap("ByteBuffer test".getBytes()));
56 | builder.addBytes(Bytes.fromByteArray("Bytes test".getBytes()));
57 | builder.addChar('c');
58 | builder.addDouble(123456789d);
59 | builder.addFloat(5468465f);
60 | builder.addInt(123);
61 | builder.addLong(264894651l);
62 | builder.addShort((short) 1);
63 | builder.addUTF8("utf8");
64 | String uuid = UUID.randomUUID().toString();
65 | builder.addUuid(uuid);
66 | Bytes bytes = builder.build();
67 |
68 | List parsedBytes = CompositeType.parse(bytes);
69 |
70 | assertNotNull(parsedBytes);
71 | assertEquals(13, parsedBytes.size());
72 |
73 | assertTrue(Arrays.equals(parsedBytes.get(0), Bytes.fromBoolean(true).toByteArray()));
74 | assertTrue(Arrays.equals(parsedBytes.get(1), Bytes.fromByte((byte) 5).toByteArray()));
75 | assertTrue(Arrays.equals(parsedBytes.get(2), "byte[] test".getBytes()));
76 | assertTrue(Arrays.equals(parsedBytes.get(3), "ByteBuffer test".getBytes()));
77 | assertTrue(Arrays.equals(parsedBytes.get(4), "Bytes test".getBytes()));
78 | assertTrue(Arrays.equals(parsedBytes.get(5), Bytes.fromChar('c').toByteArray()));
79 | assertTrue(Arrays.equals(parsedBytes.get(6), Bytes.fromDouble(123456789d).toByteArray()));
80 | assertTrue(Arrays.equals(parsedBytes.get(7), Bytes.fromFloat(5468465f).toByteArray()));
81 | assertTrue(Arrays.equals(parsedBytes.get(8), Bytes.fromInt(123).toByteArray()));
82 | assertTrue(Arrays.equals(parsedBytes.get(9), Bytes.fromLong(264894651l).toByteArray()));
83 | assertTrue(Arrays.equals(parsedBytes.get(10), Bytes.fromShort((short) 1).toByteArray()));
84 | assertTrue(Arrays.equals(parsedBytes.get(11), Bytes.fromUTF8("utf8").toByteArray()));
85 | assertTrue(Arrays.equals(parsedBytes.get(12), Bytes.fromUuid(uuid).toByteArray()));
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/test/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
2 | log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
3 | log4j.appender.CONSOLE.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
4 |
5 | log4j.category.org.scale7.cassandra.pelops.pool.DebuggingPool=WARN
6 | log4j.category.org.scale7.cassandra.pelops.ManagerOperand=WARN
7 | log4j.category.org.scale7.cassandra.pelops.Connection=WARN
8 |
9 | log4j.category.org.apache.cassandra=ERROR
10 |
11 | log4j.rootLogger=DEBUG, CONSOLE
--------------------------------------------------------------------------------