Author: eric
Date: Thu May 28 15:51:11 2015
New Revision: 1682267
URL: http://svn.apache.org/r1682267
Log:
Add missing files to support Cassandra table creation, patch contributed by
Benoit Tellier (MAILBOX-226)
Added:
james/mailbox/trunk/cassandra/README.txt
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraConstants.java
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraTableManager.java
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ClusterFactory.java
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ClusterWithKeyspaceCreatedFactory.java
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/SessionFactory.java
Removed:
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraSession.java
Added: james/mailbox/trunk/cassandra/README.txt
URL:
http://svn.apache.org/viewvc/james/mailbox/trunk/cassandra/README.txt?rev=1682267&view=auto
==============================================================================
--- james/mailbox/trunk/cassandra/README.txt (added)
+++ james/mailbox/trunk/cassandra/README.txt Thu May 28 15:51:11 2015
@@ -0,0 +1,18 @@
+= Cassandra Mailbox implementation
+
+This Mailbox sub-project is about providing a scalable mailbox implementation
relying on Cassandra database.
+
+Concurrency is handled by this implementation while performing writes using
Lightweight transactions. You do not need to lock anything, or provide utils to
lock anything, when using this implementation.
+
+== Configuration
+
+The configuration is achieved through Spring. The file is
'src/main/resources/META-INF/spring/mailbox-cassandra.xml' .
+
+The components are instanciated and wired together.
+
+What might interest you the most is the way you want to connect your Cassandra
cluster.
+
+Factories are used. You have :
+ * ClusterFactory : you specify which Cassandra servers you want to connect,
with ( optional ) which user name and password to use.
+ * ClusterWithKeyspaceCreatedFactory : This ( optional ) component creates a
Keyspace if it does not already exists. You may want to skip this step in
production environment.
+ * SessionFactory : Connect the appropriated Keyspace, to create a Session
our application can work with.
\ No newline at end of file
Added:
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraConstants.java
URL:
http://svn.apache.org/viewvc/james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraConstants.java?rev=1682267&view=auto
==============================================================================
---
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraConstants.java
(added)
+++
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraConstants.java
Thu May 28 15:51:11 2015
@@ -0,0 +1,24 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.mailbox.cassandra;
+
+public interface CassandraConstants {
+ int LIGHTWEIGHT_TRANSACTION_APPLIED = 0;
+}
Added:
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraTableManager.java
URL:
http://svn.apache.org/viewvc/james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraTableManager.java?rev=1682267&view=auto
==============================================================================
---
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraTableManager.java
(added)
+++
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraTableManager.java
Thu May 28 15:51:11 2015
@@ -0,0 +1,149 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.mailbox.cassandra;
+
+import static com.datastax.driver.core.DataType.*;
+
+import com.datastax.driver.core.querybuilder.QueryBuilder;
+import com.datastax.driver.core.schemabuilder.Create;
+
+import com.datastax.driver.core.Session;
+import com.datastax.driver.core.schemabuilder.SchemaBuilder;
+import com.datastax.driver.core.schemabuilder.SchemaStatement;
+import org.apache.james.mailbox.cassandra.table.CassandraACLTable;
+import org.apache.james.mailbox.cassandra.table.CassandraMailboxCountersTable;
+import org.apache.james.mailbox.cassandra.table.CassandraMailboxTable;
+import org.apache.james.mailbox.cassandra.table.CassandraMessageTable;
+import org.apache.james.mailbox.cassandra.table.CassandraMessageUidTable;
+import org.apache.james.mailbox.cassandra.table.CassandraSubscriptionTable;
+
+import java.util.Arrays;
+
+public class CassandraTableManager {
+
+ private Session session;
+
+ enum TABLE {
+ Mailbox(CassandraMailboxTable.TABLE_NAME,
+ SchemaBuilder.createTable(CassandraMailboxTable.TABLE_NAME)
+ .ifNotExists()
+ .addPartitionKey(CassandraMailboxTable.ID, uuid())
+ .addColumn(CassandraMailboxTable.NAMESPACE, text())
+ .addColumn(CassandraMailboxTable.USER, text())
+ .addColumn(CassandraMailboxTable.NAME, text())
+ .addColumn(CassandraMailboxTable.PATH, text())
+ .addColumn(CassandraMailboxTable.UIDVALIDITY, bigint())),
+ MailboxCounter(CassandraMailboxCountersTable.TABLE_NAME,
+ SchemaBuilder.createTable(CassandraMailboxCountersTable.TABLE_NAME)
+ .ifNotExists()
+ .addPartitionKey(CassandraMailboxCountersTable.MAILBOX_ID,
uuid())
+ .addColumn(CassandraMailboxCountersTable.COUNT, counter())
+ .addColumn(CassandraMailboxCountersTable.UNSEEN, counter())
+ .addColumn(CassandraMailboxCountersTable.NEXT_MOD_SEQ,
counter())),
+ MessageUid(CassandraMessageUidTable.TABLE_NAME,
+ SchemaBuilder.createTable(CassandraMessageUidTable.TABLE_NAME)
+ .ifNotExists()
+ .addPartitionKey(CassandraMessageUidTable.MAILBOX_ID, uuid())
+ .addColumn(CassandraMessageUidTable.NEXT_UID, bigint())),
+ Message(CassandraMessageTable.TABLE_NAME,
+ SchemaBuilder.createTable(CassandraMessageTable.TABLE_NAME)
+ .ifNotExists()
+ .addPartitionKey(CassandraMessageTable.MAILBOX_ID, uuid())
+ .addClusteringColumn(CassandraMessageTable.IMAP_UID, bigint())
+ .addColumn(CassandraMessageTable.INTERNAL_DATE, timestamp())
+ .addColumn(CassandraMessageTable.BODY_START_OCTET, cint())
+ .addColumn(CassandraMessageTable.BODY_OCTECTS, cint())
+ .addColumn(CassandraMessageTable.TEXTUAL_LINE_COUNT, bigint())
+ .addColumn(CassandraMessageTable.MOD_SEQ, bigint())
+ .addColumn(CassandraMessageTable.MEDIA_TYPE, text())
+ .addColumn(CassandraMessageTable.SUB_TYPE, text())
+ .addColumn(CassandraMessageTable.FULL_CONTENT_OCTETS, cint())
+ .addColumn(CassandraMessageTable.BODY_CONTENT, blob())
+ .addColumn(CassandraMessageTable.HEADER_CONTENT, blob())
+ .addColumn(CassandraMessageTable.Flag.ANSWERED, cboolean())
+ .addColumn(CassandraMessageTable.Flag.DELETED, cboolean())
+ .addColumn(CassandraMessageTable.Flag.DRAFT, cboolean())
+ .addColumn(CassandraMessageTable.Flag.FLAGGED, cboolean())
+ .addColumn(CassandraMessageTable.Flag.RECENT, cboolean())
+ .addColumn(CassandraMessageTable.Flag.SEEN, cboolean())
+ .addColumn(CassandraMessageTable.Flag.USER, cboolean())
+ .addColumn(CassandraMessageTable.FLAG_VERSION, bigint())),
+ Subscription(CassandraSubscriptionTable.TABLE_NAME,
+ SchemaBuilder.createTable(CassandraSubscriptionTable.TABLE_NAME)
+ .ifNotExists()
+ .addPartitionKey(CassandraSubscriptionTable.MAILBOX, text())
+ .addClusteringColumn(CassandraSubscriptionTable.USER, text())
+ ),
+ Acl(CassandraACLTable.TABLE_NAME,
+ SchemaBuilder.createTable(CassandraACLTable.TABLE_NAME)
+ .ifNotExists()
+ .addPartitionKey(CassandraACLTable.ID, uuid())
+ .addColumn(CassandraACLTable.ACL, text())
+ .addColumn(CassandraACLTable.VERSION, bigint())
+ )
+ ;
+ private Create createStatement;
+ private String name;
+
+ TABLE(String name, Create createStatement) {
+ this.createStatement = createStatement;
+ this.name = name;
+ }
+ }
+
+ enum INDEX {
+ MailboxPath(SchemaBuilder.createIndex(CassandraMailboxTable.TABLE_NAME)
+ .ifNotExists()
+ .onTable(CassandraMailboxTable.TABLE_NAME)
+ .andColumn(CassandraMailboxTable.PATH));
+ private SchemaStatement createIndexStatement;
+
+ INDEX(SchemaStatement createIndexStatement) {
+ this.createIndexStatement = createIndexStatement;
+ }
+ }
+
+ public CassandraTableManager(Session session) {
+ this.session = session;
+ }
+
+ public CassandraTableManager ensureAllTables() {
+ Arrays.asList(TABLE.values())
+ .forEach(
+ (table) -> session.execute(table.createStatement)
+ );
+ Arrays.asList(INDEX.values())
+ .forEach(
+ (table) -> session.execute(table.createIndexStatement)
+ );
+ return this;
+ }
+
+ public void clearAllTables() {
+ Arrays.asList(TABLE.values())
+ .forEach(
+ (table) -> clearTable(table.name)
+ );
+ }
+
+ private void clearTable(String tableName) {
+ session.execute(QueryBuilder.truncate(tableName));
+ }
+}
Added:
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ClusterFactory.java
URL:
http://svn.apache.org/viewvc/james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ClusterFactory.java?rev=1682267&view=auto
==============================================================================
---
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ClusterFactory.java
(added)
+++
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ClusterFactory.java
Thu May 28 15:51:11 2015
@@ -0,0 +1,69 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.mailbox.cassandra;
+
+import com.datastax.driver.core.Cluster;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
+public class ClusterFactory {
+
+ public static class CassandraServer {
+ private String ip;
+ private int port;
+
+ public CassandraServer(String ip, int port) {
+ this.ip = ip;
+ this.port = port;
+ }
+ }
+
+ private final static String DEFAULT_CLUSTER_IP = "localhost";
+ private final static int DEFAULT_CLUSTER_PORT = 9042;
+
+ public Cluster createClusterForClusterWithPassWord(List<CassandraServer>
servers, String userName, String password) {
+ Cluster.Builder clusterBuilder = Cluster.builder();
+ servers.forEach(
+ (server) ->
clusterBuilder.addContactPoint(server.ip).withPort(server.port)
+ );
+ if(!Strings.isNullOrEmpty(userName) &&
!Strings.isNullOrEmpty(password)) {
+ clusterBuilder.withCredentials(userName, password);
+ }
+ return clusterBuilder.build();
+ }
+
+ public Cluster
createClusterForClusterWithoutPassWord(List<CassandraServer> servers) {
+ return createClusterForClusterWithPassWord(servers, null, null);
+ }
+
+ public Cluster createClusterForSingleServerWithPassWord(String ip, int
port, String userName, String password) {
+ return createClusterForClusterWithPassWord(ImmutableList.of(new
CassandraServer(ip, port)), userName, password);
+ }
+
+ public Cluster createClusterForSingleServerWithoutPassWord(String ip, int
port) {
+ return createClusterForClusterWithPassWord(ImmutableList.of(new
CassandraServer(ip, port)), null, null);
+ }
+
+ public Cluster createDefaultSession() {
+ return createClusterForSingleServerWithoutPassWord(DEFAULT_CLUSTER_IP,
DEFAULT_CLUSTER_PORT);
+ }
+}
Added:
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ClusterWithKeyspaceCreatedFactory.java
URL:
http://svn.apache.org/viewvc/james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ClusterWithKeyspaceCreatedFactory.java?rev=1682267&view=auto
==============================================================================
---
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ClusterWithKeyspaceCreatedFactory.java
(added)
+++
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ClusterWithKeyspaceCreatedFactory.java
Thu May 28 15:51:11 2015
@@ -0,0 +1,32 @@
+package org.apache.james.mailbox.cassandra;
+
+import com.datastax.driver.core.Cluster;
+import com.datastax.driver.core.Session;
+
+public class ClusterWithKeyspaceCreatedFactory {
+
+ private final static int DEFAULT_REPLICATION_FACTOR = 1;
+
+ public Cluster clusterWithInitializedKeyspace(Cluster cluster, String
keyspace, int replicationFactor) {
+ if (isKeyspacePresent(cluster, keyspace)) {
+ createKeyspace(cluster, keyspace, replicationFactor);
+ }
+ return cluster;
+ }
+
+ public Cluster clusterWithInitializedKeyspace(Cluster cluster, String
keyspace) {
+ return clusterWithInitializedKeyspace(cluster, keyspace,
DEFAULT_REPLICATION_FACTOR);
+ }
+
+ private boolean isKeyspacePresent(Cluster cluster, String keyspace) {
+ return cluster.getMetadata().getKeyspace(keyspace) == null;
+ }
+
+ private void createKeyspace(Cluster cluster, String keyspace, int
replicationFactor) {
+ try (Session session = cluster.connect()) {
+ session.execute("CREATE KEYSPACE IF NOT EXISTS " + keyspace
+ + " WITH replication = {'class':'SimpleStrategy',
'replication_factor':" + replicationFactor + "};");
+ }
+ }
+
+}
Added:
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/SessionFactory.java
URL:
http://svn.apache.org/viewvc/james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/SessionFactory.java?rev=1682267&view=auto
==============================================================================
---
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/SessionFactory.java
(added)
+++
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/SessionFactory.java
Thu May 28 15:51:11 2015
@@ -0,0 +1,39 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.mailbox.cassandra;
+
+import com.datastax.driver.core.Cluster;
+import com.datastax.driver.core.Session;
+
+public class SessionFactory {
+ private final static String DEFAULT_KEYSPACE_NAME = "apache_james";
+
+ public Session createSession(Cluster cluster, String keyspace) {
+ Session session = cluster.connect(keyspace);
+ new CassandraTableManager(session)
+ .ensureAllTables();
+ return session;
+ }
+
+ public Session createSession(Cluster cluster) {
+ return createSession(cluster, DEFAULT_KEYSPACE_NAME);
+ }
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]