Author: ivol37 at gmail.com
Date: Tue Jan 11 11:34:28 2011
New Revision: 585
Log:
[AMDATU-243] Added API to update the replication factor and to create keyspaces
with a certain replication factor other then the default
Modified:
trunk/amdatu-cassandra/cassandra-application/src/main/java/org/amdatu/cassandra/application/CassandraDaemonService.java
trunk/amdatu-cassandra/cassandra-application/src/main/java/org/amdatu/cassandra/application/service/CassandraDaemonServiceImpl.java
trunk/amdatu-cassandra/cassandra-application/src/main/resources/conf/cassandra.yaml
trunk/amdatu-core/config-filebased/src/main/resources/conf/org.amdatu.core.cassandra.application.cfg
trunk/amdatu-example/course-service/src/main/java/org/amdatu/example/course/service/service/ProfileDataProvider.java
Modified:
trunk/amdatu-cassandra/cassandra-application/src/main/java/org/amdatu/cassandra/application/CassandraDaemonService.java
==============================================================================
---
trunk/amdatu-cassandra/cassandra-application/src/main/java/org/amdatu/cassandra/application/CassandraDaemonService.java
(original)
+++
trunk/amdatu-cassandra/cassandra-application/src/main/java/org/amdatu/cassandra/application/CassandraDaemonService.java
Tue Jan 11 11:34:28 2011
@@ -80,18 +80,54 @@
boolean keyspaceExists(String keyspaceName) throws TException,
InvalidRequestException;
/**
- * Adds a keyspace with the specified name. If the keyspace was added true
is returned. If a keyspace with that name
- * already exsisted, false is returned. Note that keyspaces in Cassandra
are case-sensitive. If for any reason
- * creation of the keyspace failed, an InvalidRequestException or
TException is thrown.
+ * Adds a keyspace with the specified name and the default replication
factor. If the keyspace was added true
+ * is returned. If a keyspace with that name already exsisted, false is
returned. Note that keyspaces in Cassandra
+ * are case-sensitive. If for any reason creation of the keyspace failed,
an InvalidRequestException or TException
+ * is thrown.
*
* @param name Name of the keyspace to add (case-sensitive)
- * * @return true if a new keyspace was added, false if a keyspace with
this name already existed.
+ * @return true if a new keyspace was added, false if a keyspace with this
name already existed.
* @throws InvalidRequestException In case a keyspace with the specified
name already exists.
* @throws TException In case an error occurred while adding the keyspace
*/
boolean addKeyspace(String name) throws InvalidRequestException,
TException;
/**
+ * Adds a keyspace with the specified name and replication factor. If the
keyspace was added true
+ * is returned. If a keyspace with that name already exsisted, false is
returned. Note that keyspaces in Cassandra
+ * are case-sensitive. If for any reason creation of the keyspace failed,
an InvalidRequestException or TException
+ * is thrown.
+ * The replication factor defines the amount of nodes to which the data
contained by this keyspace will
+ * be replicated. The replication factor of an existing keyspace can be
changed using
+ *
+ * @param name Name of the keyspace to add (case-sensitive)
+ * @param replicationFactor The replication factor to create the keyspace
with.
+ * @return true if a new keyspace was added, false if a keyspace with this
name already existed.
+ * @throws InvalidRequestException In case a keyspace with the specified
name already exists.
+ * @throws TException In case an error occurred while adding the keyspace
+ */
+ boolean addKeyspace(String name, int replicationFactor) throws
InvalidRequestException, TException;
+
+ /**
+ * Updates the replication factor of all existing keyspaces, except the
system keyspace.
+ * @param replicationFactor The new replication factor to assign to all
keyspaces
+ * @throws InvalidRequestException In case the replicatio nfactor is
invalid
+ * @throws TException In case an error occurred while updating the keyspace
+ */
+ void setReplicationFactor(int replicationFactor) throws
InvalidRequestException, TException;
+
+ /**
+ * Updates the replication factor of an existing keyspace. If the
replication factor of the given keyspace
+ * already equals the new replication factor, this method returns without
doing anything.
+ * @param keyspace The name of the keyspace to update
+ * @param replicationFactor The new replication factor to assign
+ * @throws NotFoundException In case a keyspace with this name could not
be found
+ * @throws InvalidRequestException In case the replicatio nfactor is
invalid
+ * @throws TException In case an error occurred while updating the keyspace
+ */
+ void setReplicationFactor(String keyspace, int replicationFactor) throws
NotFoundException, InvalidRequestException, TException;
+
+ /**
* Drops the keyspace with the specified name. All data (i.e.
ColumnFamily's) contained
* by the keyspace are also removed. Note that keyspace names are case
sensitive. If no keyspace
* exists with the specified name, false is returned. If the keyspace was
removed true is returned.
Modified:
trunk/amdatu-cassandra/cassandra-application/src/main/java/org/amdatu/cassandra/application/service/CassandraDaemonServiceImpl.java
==============================================================================
---
trunk/amdatu-cassandra/cassandra-application/src/main/java/org/amdatu/cassandra/application/service/CassandraDaemonServiceImpl.java
(original)
+++
trunk/amdatu-cassandra/cassandra-application/src/main/java/org/amdatu/cassandra/application/service/CassandraDaemonServiceImpl.java
Tue Jan 11 11:34:28 2011
@@ -142,9 +142,13 @@
}
public synchronized boolean addKeyspace(String name) throws
InvalidRequestException, TException {
+ return addKeyspace(name,
m_configuration.getDefaultReplicationFactor());
+ }
+
+ public synchronized boolean addKeyspace(String name, int
replicationFactor) throws InvalidRequestException, TException {
if (!keyspaceExists(name)) {
List<CfDef> empty = new ArrayList<CfDef>();
- KsDef ksDef = new KsDef(name, DEFAULT_PLACEMENT_STRATEGY,
m_configuration.getDefaultReplicationFactor(), empty);
+ KsDef ksDef = new KsDef(name, DEFAULT_PLACEMENT_STRATEGY,
replicationFactor, empty);
try {
m_cassandraServer.system_add_keyspace(ksDef);
} catch (InvalidRequestException e) {
@@ -171,6 +175,26 @@
}
}
+ public synchronized void setReplicationFactor(int replicationFactor)
throws InvalidRequestException, TException {
+ List<KsDef> keyspaces = m_cassandraServer.describe_keyspaces();
+ for (KsDef keyspace : keyspaces) {
+ if (keyspace.getReplication_factor() != replicationFactor) {
+ keyspace.setReplication_factor(replicationFactor);
+ keyspace.setCf_defs(null);
+ m_cassandraServer.system_update_keyspace(keyspace);
+ }
+ }
+ }
+
+ public synchronized void setReplicationFactor(String keyspace, int
replicationFactor) throws NotFoundException, InvalidRequestException,
TException {
+ KsDef ksDef = m_cassandraServer.describe_keyspace(keyspace);
+ if (ksDef.getReplication_factor() != replicationFactor) {
+ ksDef.setReplication_factor(replicationFactor);
+ ksDef.setCf_defs(null);
+ m_cassandraServer.system_update_keyspace(ksDef);
+ }
+ }
+
public synchronized boolean dropKeyspace(String keyspace) throws
InvalidRequestException, TException {
if (keyspaceExists(keyspace)) {
m_cassandraServer.system_drop_keyspace(keyspace);
@@ -225,7 +249,6 @@
m_logService.log(LogService.LOG_DEBUG, "ColumnFamily '" + cfName +
"' was not added to keyspace '" + keyspace + "' since it already existed");
return false;
}
-
}
public boolean isColumnFamilyChanged(String keyspace, String cfName,
String columnType, String comparatorType,
Modified:
trunk/amdatu-cassandra/cassandra-application/src/main/resources/conf/cassandra.yaml
==============================================================================
---
trunk/amdatu-cassandra/cassandra-application/src/main/resources/conf/cassandra.yaml
(original)
+++
trunk/amdatu-cassandra/cassandra-application/src/main/resources/conf/cassandra.yaml
Tue Jan 11 11:34:28 2011
@@ -38,14 +38,28 @@
# authorization backend, implementing IAuthority; used to limit access/provide
permissions
authority: org.apache.cassandra.auth.AllowAllAuthority
-# any IPartitioner may be used, including your own as long as it is on
-# the classpath. Out of the box, Cassandra provides
-# org.apache.cassandra.dht.RandomPartitioner
+# The partitioner is responsible for distributing rows (by key) across
+# nodes in the cluster. Any IPartitioner may be used, including your
+# own as long as it is on the classpath. Out of the box, Cassandra
+# provides org.apache.cassandra.dht.RandomPartitioner
# org.apache.cassandra.dht.ByteOrderedPartitioner,
-# org.apache.cassandra.dht.OrderPreservingPartitioner, and
-# org.apache.cassandra.dht.CollatingOrderPreservingPartitioner.
-# (CollatingOPP colates according to EN,US rules, not naive byte
-# ordering. Use this as an example if you need locale-aware collation.)
+# org.apache.cassandra.dht.OrderPreservingPartitioner (deprecated),
+# and org.apache.cassandra.dht.CollatingOrderPreservingPartitioner
+# (deprecated).
+#
+# - RandomPartitioner distributes rows across the cluster evenly by md5.
+# When in doubt, this is the best option.
+# - ByteOrderedPartitioner orders rows lexically by key bytes. BOP allows
+# scanning rows in key order, but the ordering can generate hot spots
+# for sequential insertion workloads.
+# - OrderPreservingPartitioner is an obsolete form of BOP, that stores
+# - keys in a less-efficient format and only works with keys that are
+# UTF8-encoded Strings.
+# - CollatingOPP colates according to EN,US rules rather than lexical byte
+# ordering. Use this as an example if you need custom collation.
+#
+# See http://wiki.apache.org/cassandra/Operations for more on
+# partitioners and token selection.
partitioner: org.apache.cassandra.dht.RandomPartitioner
# directories where Cassandra should store data on disk.
@@ -215,7 +229,9 @@
# 'pinning' of replicas to hosts in order to increase cache capacity.
# The badness threshold will control how much worse the pinned host has to be
# before the dynamic snitch will prefer other replicas over it. This is
-# expressed as a double which represents a percentage.
+# expressed as a double which represents a percentage. Thus, a value of
+# 0.2 means Cassandra would continue to prefer the static snitch values
+# until the pinned host was 20% worse than the fastest.
dynamic_snitch_badness_threshold: 0.0
# request_scheduler -- Set this to a class that implements
Modified:
trunk/amdatu-core/config-filebased/src/main/resources/conf/org.amdatu.core.cassandra.application.cfg
==============================================================================
---
trunk/amdatu-core/config-filebased/src/main/resources/conf/org.amdatu.core.cassandra.application.cfg
(original)
+++
trunk/amdatu-core/config-filebased/src/main/resources/conf/org.amdatu.core.cassandra.application.cfg
Tue Jan 11 11:34:28 2011
@@ -41,6 +41,9 @@
# the two nodes). In case all data should be available on all nodes in the
cluster, which
# is necessary in case the node should also be able to run stand-alone, the
replication
# factor should equal the number of nodes in the cluster.
+# Note that upon the very first boot of a node, the replication factor must be
1 as the
+# replication factor may never be higher then the amount of nodes in the
cluster. Usually
+# the replication factor upon first boot is always 1, to be increased at
runtime.
default_replication_factor=${cassandra.default_replication_factor}
# The read consistency level to apply. The read consistencly level determines
the
Modified:
trunk/amdatu-example/course-service/src/main/java/org/amdatu/example/course/service/service/ProfileDataProvider.java
==============================================================================
---
trunk/amdatu-example/course-service/src/main/java/org/amdatu/example/course/service/service/ProfileDataProvider.java
(original)
+++
trunk/amdatu-example/course-service/src/main/java/org/amdatu/example/course/service/service/ProfileDataProvider.java
Tue Jan 11 11:34:28 2011
@@ -62,6 +62,8 @@
// FIXME: works for now but we should set some 'initialized'
property in config admin
// but since we are using fileinstall, that cannot be done using
ConfigurationAdmin
if (m_userAdmin.getRoles(null) == null ||
m_userAdmin.getRoles(null).length <= 2) {
+ m_logService.log(LogService.LOG_DEBUG, "Less then 2 roles
found in UserAdmin, creating test roles");
+
// Create 8 test profiles for "John Doe", "Jane Doe", "George
Doe", "Melissa Doe",
// "Ted Brown", "Elisa Devis", "Mario Rossi" and "Maija
Meikalainen"
createTestPerson("johnd", "John Doe", 43, new
String[]{"janed", "georged", "melissad", "marior"});
@@ -72,18 +74,18 @@
createTestPerson("elisad", "Elisa Davis", 15, new
String[]{"melissad"});
createTestPerson("marior", "Mario Rossi", 54, new
String[]{"johnd"});
createTestPerson("maijam", "Maija Meik\u00e4l\u00e4inen", 37,
new String[]{"janed"});
-
+
// Now create roles 'Teacher' and 'Student' and assign basic
members
Group teacher = (Group) m_userAdmin.createRole("Teacher",
Role.GROUP);
teacher.addMember(m_userAdmin.getRole("marior"));
teacher.addMember(m_userAdmin.getRole("maijam"));
-
+
Group student = (Group) m_userAdmin.createRole("Student",
Role.GROUP);
student.addMember(m_userAdmin.getRole("elisad"));
student.addMember(m_userAdmin.getRole("melissad"));
student.addMember(m_userAdmin.getRole("tedb"));
student.addMember(m_userAdmin.getRole("georged"));
-
+
Group parent = (Group) m_userAdmin.createRole("Parent",
Role.GROUP);
parent.addMember(m_userAdmin.getRole("janed"));
parent.addMember(m_userAdmin.getRole("johnd"));