Skip to content
This repository was archived by the owner on Jun 7, 2023. It is now read-only.

Commit ca9b940

Browse files
author
Rustam Aliyev
committed
Use C* as a blob storage for small emails. Major refactoring of blob
storage. fixed #32
1 parent 583a6da commit ca9b940

34 files changed

+1300
-248
lines changed

config/elasticinbox.cml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ CREATE COLUMN FAMILY MessageMetadata WITH
2626
caching = keys_only AND
2727
comment='Message metadata including headers, labels, markers, physical location, etc.';
2828

29+
CREATE COLUMN FAMILY MessageBlob WITH
30+
key_validation_class = 'CompositeType(TimeUUIDType, Int32Type)' AND
31+
comparator = Int32Type AND
32+
caching = keys_only AND
33+
comment='Chunked message blobs';
34+
2935
CREATE COLUMN FAMILY IndexLabels WITH
3036
key_validation_class = UTF8Type AND
3137
comparator = TimeUUIDType AND

config/elasticinbox.yaml

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ lmtp_enable_pop3: true
2626
pop3_port: 2110
2727
pop3_max_connections: 20
2828

29-
### Metadata storage driver
30-
# currently only "cassandra" supported
31-
metadata_storage_driver: cassandra
29+
### Database settings
30+
# Database used for storing metadata of accounts, labels and messages.
31+
# Optionally, it is possible to store blobs in the database (see database_blob_max_threshold).
32+
# Currently only "cassandra" is supported.
33+
database_driver: cassandra
3234

3335
# If you want to store parsed HTML and/or PLAIN text of the message body
3436
# in the metadata storage, enable below.
@@ -38,6 +40,11 @@ metadata_storage_driver: cassandra
3840
store_html_message: true
3941
store_plain_message: false
4042

43+
# Maximum blob size in bytes which can be stored in the database.
44+
# Blobs larger than this value will be stored with the deafult blob profile (blobstore_write_profile).
45+
# Set to 0 to disable using database for blobs. Currently value can't be more than 128K.
46+
database_blob_max_size: 65536
47+
4148
### Cassandra settings
4249
# Specify Cassandra hosts (multiple for LB), cluster name, keyspace
4350
# and auto discovery
@@ -85,10 +92,10 @@ blobstore_profiles:
8592
# only one profile can be used for writing at the same time
8693
blobstore_write_profile: fs-local
8794

88-
# compress objects written to the blob store
95+
# compress objects written to the blob store (including database blobs)
8996
blobstore_enable_compression: true
9097

91-
# encrypt objects written to the blob store
98+
# encrypt objects written to the blob store (excluding database blobs)
9299
blobstore_enable_encryption: false
93100
#blobstore_default_encryption_key: mykey1
94101

itests/src/test/java/com/elasticinbox/itests/AbstractIntegrationTest.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import static org.ops4j.pax.exam.CoreOptions.felix;
55
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
66
import static org.ops4j.pax.exam.CoreOptions.options;
7-
import static org.ops4j.pax.exam.CoreOptions.repository;
87
import static org.ops4j.pax.exam.CoreOptions.scanDir;
98
import static org.ops4j.pax.exam.CoreOptions.systemProperty;
109
import static org.ops4j.pax.exam.CoreOptions.workingDirectory;
@@ -46,7 +45,7 @@ public Option[] config()
4645
//junitBundles(),
4746
felix().version("3.2.2"),
4847
workingDirectory("target/paxrunner/"),
49-
repository("https://repository.apache.org/snapshots/").allowSnapshots(),
48+
//repository("https://repository.apache.org/snapshots/").allowSnapshots(),
5049

5150
// Configs
5251
systemProperty("elasticinbox.config").value("../test-classes/elasticinbox.yaml"),

itests/src/test/java/com/elasticinbox/itests/Pop3IT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public Option[] config()
9494
public void testListUidl() throws IOException
9595
{
9696
initAccount();
97-
97+
9898
// load messages with POP3 label
9999
long mailSizeRegular = getResourceSize(EMAIL_REGULAR);
100100
long mailSizeAttach = getResourceSize(EMAIL_LARGE_ATT);

itests/src/test/resources/elasticinbox.yaml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ lmtp_enable_pop3: true
2626
pop3_port: 2110
2727
pop3_max_connections: 20
2828

29-
### Metadata storage driver
30-
# currently only "cassandra" supported
31-
metadata_storage_driver: cassandra
29+
### Database settings
30+
# Database used for storing metadata of accounts, labels and messages.
31+
# Optionally, it is possible to store blobs in the database (see database_blob_max_threshold).
32+
# Currently only "cassandra" is supported.
33+
database_driver: cassandra
3234

3335
# If you want to store parsed HTML and/or PLAIN text of the message body
3436
# in the metadata storage, enable below.
@@ -38,6 +40,11 @@ metadata_storage_driver: cassandra
3840
store_html_message: true
3941
store_plain_message: false
4042

43+
# Maximum blob size in bytes which can be stored in the database.
44+
# Blobs larger than this value will be stored with the deafult blob profile (blobstore_write_profile).
45+
# Set to 0 to disable using database for blobs. Currently value can't be more than 128K.
46+
database_blob_max_size: 65536
47+
4148
### Cassandra settings
4249
# Specify Cassandra hosts (multiple for LB), cluster name, keyspace
4350
# and auto discovery

modules/config/src/main/java/com/elasticinbox/config/Config.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,11 @@ public class Config
5353
public Integer pop3_port;
5454
public Integer pop3_max_connections;
5555

56-
// metadata storage settings
57-
public String metadata_storage_driver;
56+
// Database settings
57+
public String database_driver;
5858
public Boolean store_html_message;
5959
public Boolean store_plain_message;
60+
public Long database_blob_max_size;
6061

6162
// Cassandra settings
6263
public List<String> cassandra_hosts;

modules/config/src/main/java/com/elasticinbox/config/Configurator.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,18 @@ static URI getStorageConfigURL() throws ConfigurationException
112112
// TODO: add config verification here
113113
// ...
114114

115+
// verify max database blob size
116+
if(conf.database_blob_max_size > DatabaseConstants.MAX_BLOB_SIZE) {
117+
throw new ConfigurationException("Blobs larger than "
118+
+ DatabaseConstants.MAX_BLOB_SIZE + " bytes cannot be stored in the database");
119+
}
120+
121+
// verify that blobstore profile name is not conflicting with internal name
122+
if (conf.blobstore_profiles.containsKey(DatabaseConstants.DATABASE_PROFILE)) {
123+
throw new ConfigurationException("BlobStore profile name cannot be '"
124+
+ DatabaseConstants.DATABASE_PROFILE + "'");
125+
}
126+
115127
// verify that default blobstore profile exists
116128
if (!conf.blobstore_profiles.containsKey(conf.blobstore_write_profile)) {
117129
throw new ConfigurationException("Default BlobStore Profile '"
@@ -167,8 +179,12 @@ public static Integer getPop3MaxConnections() {
167179
return conf.pop3_max_connections;
168180
}
169181

170-
public static String getMetadataStorageDriver() {
171-
return (conf.metadata_storage_driver.equalsIgnoreCase("cassandra")) ? "CASSANDRA" : "UNKNOWN";
182+
public static String getDatabaseDriver() {
183+
return (conf.database_driver.equalsIgnoreCase("cassandra")) ? "CASSANDRA" : "UNKNOWN";
184+
}
185+
186+
public static Long getDatabaseBlobMaxSize() {
187+
return conf.database_blob_max_size;
172188
}
173189

174190
public static List<String> getCassandraHosts() {
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/**
2+
* Copyright (c) 2011-2013 Optimax Software Ltd.
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
*
8+
* * Redistributions of source code must retain the above copyright notice,
9+
* this list of conditions and the following disclaimer.
10+
* * Redistributions in binary form must reproduce the above copyright notice,
11+
* this list of conditions and the following disclaimer in the documentation
12+
* and/or other materials provided with the distribution.
13+
* * Neither the name of Optimax Software, ElasticInbox, nor the names
14+
* of its contributors may be used to endorse or promote products derived
15+
* from this software without specific prior written permission.
16+
*
17+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
21+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27+
*/
28+
29+
package com.elasticinbox.config;
30+
31+
public class DatabaseConstants
32+
{
33+
/** Maximum blob size allowed in database. 128KB */
34+
public static long MAX_BLOB_SIZE = 0x20000;
35+
36+
/** Maximum blob block size. 128KB */
37+
public static long BLOB_BLOCK_SIZE = 0x20000;
38+
39+
/** Reserved profile name for internal database storage (e.g. Cassandra) */
40+
public static final String DATABASE_PROFILE = "db";
41+
}

modules/core/osgi.bnd

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ Export-Package: \
1313
com.elasticinbox.core.log
1414

1515
Private-Package: \
16-
com.elasticinbox.core.blob.store,\
17-
com.elasticinbox.core.blob.naming,\
16+
com.elasticinbox.core.blob.*,\
1817
com.elasticinbox.core.cassandra,\
1918
com.elasticinbox.core.cassandra.persistence,\
2019
com.elasticinbox.core.cassandra.utils

modules/core/src/main/java/com/elasticinbox/core/MessageDAO.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,9 @@ public void removeLabel(Mailbox mailbox, Set<Integer> labelIds, UUID messageId)
224224
*
225225
* @param mailbox
226226
* @param age
227+
* @throws IOException
227228
*/
228-
public void purge(Mailbox mailbox, Date age);
229+
public void purge(Mailbox mailbox, Date age) throws IOException;
229230

230231
/**
231232
* Calculates counters for all labels bu scanning through all messages. Used

0 commit comments

Comments
 (0)