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"));

Reply via email to