JAMES-2082 From MessageMapper layer, write to V2, read from V2 or V1 and Migration on fly
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/31567b21 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/31567b21 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/31567b21 Branch: refs/heads/master Commit: 31567b215cfcd32def54adc7bb567652f3c5ae33 Parents: 3b621a3 Author: benwa <btell...@linagora.com> Authored: Thu Jul 6 17:15:51 2017 +0700 Committer: Antoine Duprat <adup...@linagora.com> Committed: Mon Jul 10 14:23:55 2017 +0200 ---------------------------------------------------------------------- .../CassandraMailboxSessionMapperFactory.java | 12 +- .../cassandra/mail/AttachmentLoader.java | 18 ++ .../cassandra/mail/CassandraMessageDAO.java | 16 +- .../mail/CassandraMessageIdMapper.java | 30 ++- .../cassandra/mail/CassandraMessageMapper.java | 48 +++-- .../mail/MessageWithoutAttachment.java | 10 + .../mail/migration/V1ToV2Migration.java | 90 +++++++++ .../modules/CassandraMessageModule.java | 4 +- .../CassandraMailboxManagerProvider.java | 5 + .../CassandraMailboxManagerStressTest.java | 2 + .../cassandra/CassandraMailboxManagerTest.java | 2 + .../CassandraSubscriptionManagerTest.java | 3 + .../cassandra/CassandraTestSystemFixture.java | 7 + .../CassandraMailboxManagerAttachmentTest.java | 9 +- .../cassandra/mail/CassandraMapperProvider.java | 10 +- .../cassandra/mail/CassandraMessageDAOTest.java | 26 ++- .../mail/migration/V1ToV2MigrationTest.java | 185 +++++++++++++++++++ .../store/mail/model/MessageMapperTest.java | 9 + .../cassandra/host/CassandraHostSystem.java | 7 + .../modules/mailbox/CassandraMailboxModule.java | 1 + 20 files changed, 446 insertions(+), 48 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/31567b21/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java index 0168e84..4ddd2db 100644 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java @@ -64,6 +64,7 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa private final CassandraUidProvider uidProvider; private final CassandraModSeqProvider modSeqProvider; private final CassandraMessageDAO messageDAO; + private final CassandraMessageDAOV2 messageDAOV2; private final CassandraMessageIdDAO messageIdDAO; private final CassandraMessageIdToImapUidDAO imapUidDAO; private final CassandraMailboxCounterDAO mailboxCounterDAO; @@ -79,7 +80,8 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa @Inject public CassandraMailboxSessionMapperFactory(CassandraUidProvider uidProvider, CassandraModSeqProvider modSeqProvider, Session session, - CassandraMessageDAO messageDAO, CassandraMessageIdDAO messageIdDAO, CassandraMessageIdToImapUidDAO imapUidDAO, + CassandraMessageDAO messageDAO, CassandraMessageDAOV2 messageDAOV2, + CassandraMessageIdDAO messageIdDAO, CassandraMessageIdToImapUidDAO imapUidDAO, CassandraMailboxCounterDAO mailboxCounterDAO, CassandraMailboxRecentsDAO mailboxRecentsDAO, CassandraMailboxDAO mailboxDAO, CassandraMailboxPathDAO mailboxPathDAO, CassandraFirstUnseenDAO firstUnseenDAO, CassandraApplicableFlagDAO applicableFlagDAO, CassandraDeletedMessageDAO deletedMessageDAO, CassandraUtils cassandraUtils, CassandraConfiguration cassandraConfiguration) { @@ -87,6 +89,7 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa this.modSeqProvider = modSeqProvider; this.session = session; this.messageDAO = messageDAO; + this.messageDAOV2 = messageDAOV2; this.messageIdDAO = messageIdDAO; this.imapUidDAO = imapUidDAO; this.mailboxCounterDAO = mailboxCounterDAO; @@ -111,6 +114,7 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa CassandraModSeqProvider modSeqProvider, Session session, CassandraMessageDAO messageDAO, + CassandraMessageDAOV2 messageDAOV2, CassandraMessageIdDAO messageIdDAO, CassandraMessageIdToImapUidDAO imapUidDAO, CassandraMailboxCounterDAO mailboxCounterDAO, @@ -121,7 +125,7 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa CassandraApplicableFlagDAO applicableFlagDAO, CassandraDeletedMessageDAO deletedMesageDAO) { - this(uidProvider, modSeqProvider, session, messageDAO, messageIdDAO, imapUidDAO, mailboxCounterDAO, + this(uidProvider, modSeqProvider, session, messageDAO, messageDAOV2, messageIdDAO, imapUidDAO, mailboxCounterDAO, mailboxRecentsDAO, mailboxDAO, mailboxPathDAO, firstUnseenDAO, applicableFlagDAO, deletedMesageDAO, CassandraUtils.WITH_DEFAULT_CONFIGURATION, CassandraConfiguration.DEFAULT_CONFIGURATION); } @@ -134,6 +138,7 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa null, (CassandraAttachmentMapper) createAttachmentMapper(mailboxSession), messageDAO, + messageDAOV2, messageIdDAO, imapUidDAO, mailboxCounterDAO, @@ -149,7 +154,8 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa public MessageIdMapper createMessageIdMapper(MailboxSession mailboxSession) throws MailboxException { return new CassandraMessageIdMapper(getMailboxMapper(mailboxSession), mailboxDAO, (CassandraAttachmentMapper) getAttachmentMapper(mailboxSession), - imapUidDAO, messageIdDAO, messageDAO, indexTableHandler, modSeqProvider, mailboxSession, cassandraConfiguration); + imapUidDAO, messageIdDAO, messageDAO, messageDAOV2, indexTableHandler, modSeqProvider, mailboxSession, + cassandraConfiguration); } @Override http://git-wip-us.apache.org/repos/asf/james-project/blob/31567b21/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/AttachmentLoader.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/AttachmentLoader.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/AttachmentLoader.java index cd70e55..59933be 100644 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/AttachmentLoader.java +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/AttachmentLoader.java @@ -24,10 +24,14 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.function.Function; +import java.util.stream.Stream; +import org.apache.commons.lang3.tuple.Pair; import org.apache.james.mailbox.model.Attachment; import org.apache.james.mailbox.model.AttachmentId; import org.apache.james.mailbox.model.MessageAttachment; +import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage; +import org.apache.james.util.FluentFutureStream; import org.apache.james.util.OptionalConverter; import com.github.steveash.guavate.Guavate; @@ -42,6 +46,20 @@ public class AttachmentLoader { this.attachmentMapper = attachmentMapper; } + public CompletableFuture<Stream<SimpleMailboxMessage>> toMailboxMessageWithAttachments( + CompletableFuture<Stream<Pair<MessageWithoutAttachment, Stream<MessageAttachmentRepresentation>>>> messageRepresentations) { + + return FluentFutureStream.of(messageRepresentations) + .thenComposeOnAll(pair -> getAttachments(pair.getRight().collect(Guavate.toImmutableList())) + .thenApply(attachments -> Pair.of(pair.getLeft(), attachments))) + .map(pair -> + pair.getLeft() + .toMailboxMessage(pair.getRight() + .stream() + .collect(Guavate.toImmutableList()))) + .completableFuture(); + } + public CompletableFuture<Collection<MessageAttachment>> getAttachments(List<MessageAttachmentRepresentation> attachmentRepresentations) { CompletableFuture<Map<AttachmentId, Attachment>> attachmentsByIdFuture = attachmentsById(attachmentRepresentations.stream() http://git-wip-us.apache.org/repos/asf/james-project/blob/31567b21/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java index d9d6eaf..ed29a11 100644 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java @@ -57,6 +57,7 @@ import org.apache.james.backends.cassandra.CassandraConfiguration; import org.apache.james.backends.cassandra.init.CassandraTypesProvider; import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor; import org.apache.james.mailbox.cassandra.CassandraMessageId; +import org.apache.james.mailbox.cassandra.Limit; import org.apache.james.mailbox.cassandra.table.CassandraMessageV1Table.Attachments; import org.apache.james.mailbox.cassandra.table.CassandraMessageV1Table.Properties; import org.apache.james.mailbox.exception.MailboxException; @@ -186,9 +187,13 @@ public class CassandraMessageDAO { return ByteBuffer.wrap(ByteStreams.toByteArray(stream)); } - public CompletableFuture<Stream<Pair<MessageWithoutAttachment, Stream<MessageAttachmentRepresentation>>>> retrieveMessages(List<ComposedMessageIdWithMetaData> messageIds, FetchType fetchType, Optional<Integer> limit) { + public CompletableFuture<Stream<Pair<MessageWithoutAttachment, Stream<MessageAttachmentRepresentation>>>> retrieveMessages( + List<ComposedMessageIdWithMetaData> messageIds, + FetchType fetchType, + Limit limit + ) { return CompletableFutureUtil.chainAll( - getLimitedIdStream(messageIds.stream().distinct(), limit) + limit.applyOnStream(messageIds.stream().distinct()) .collect(JamesCollectors.chunker(cassandraConfiguration.getMessageReadChunkSize())), ids -> FluentFutureStream.of( ids.stream() @@ -199,13 +204,6 @@ public class CassandraMessageDAO { .thenApply(stream -> stream.flatMap(Function.identity())); } - private Stream<ComposedMessageIdWithMetaData> getLimitedIdStream(Stream<ComposedMessageIdWithMetaData> messageIds, Optional<Integer> limit) { - return limit - .filter(value -> value > 0) - .map(messageIds::limit) - .orElse(messageIds); - } - private CompletableFuture<ResultSet> retrieveRow(ComposedMessageIdWithMetaData messageId, FetchType fetchType) { CassandraMessageId cassandraMessageId = (CassandraMessageId) messageId.getComposedMessageId().getMessageId(); http://git-wip-us.apache.org/repos/asf/james-project/blob/31567b21/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java index 81d2cf1..d84c8c8 100644 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java @@ -36,6 +36,8 @@ import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.MessageManager; import org.apache.james.mailbox.cassandra.CassandraId; import org.apache.james.mailbox.cassandra.CassandraMessageId; +import org.apache.james.mailbox.cassandra.Limit; +import org.apache.james.mailbox.cassandra.mail.migration.V1ToV2Migration; import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.model.ComposedMessageId; import org.apache.james.mailbox.model.ComposedMessageIdWithMetaData; @@ -51,6 +53,7 @@ import org.apache.james.mailbox.store.mail.ModSeqProvider; import org.apache.james.mailbox.store.mail.model.MailboxMessage; import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage; import org.apache.james.util.CompletableFutureUtil; +import org.apache.james.util.FluentFutureStream; import org.apache.james.util.OptionalConverter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -59,6 +62,7 @@ import com.github.fge.lambdas.Throwing; import com.github.fge.lambdas.functions.FunctionChainer; import com.github.steveash.guavate.Guavate; import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableList; public class CassandraMessageIdMapper implements MessageIdMapper { private static final Logger LOGGER = LoggerFactory.getLogger(CassandraMessageIdMapper.class); @@ -67,26 +71,31 @@ public class CassandraMessageIdMapper implements MessageIdMapper { private final CassandraMailboxDAO mailboxDAO; private final CassandraMessageIdToImapUidDAO imapUidDAO; private final CassandraMessageIdDAO messageIdDAO; - private final CassandraMessageDAO messageDAO; + private final CassandraMessageDAOV2 messageDAOV2; private final CassandraIndexTableHandler indexTableHandler; private final ModSeqProvider modSeqProvider; private final MailboxSession mailboxSession; private final AttachmentLoader attachmentLoader; + private final V1ToV2Migration v1ToV2Migration; private final CassandraConfiguration cassandraConfiguration; public CassandraMessageIdMapper(MailboxMapper mailboxMapper, CassandraMailboxDAO mailboxDAO, CassandraAttachmentMapper attachmentMapper, - CassandraMessageIdToImapUidDAO imapUidDAO, CassandraMessageIdDAO messageIdDAO, CassandraMessageDAO messageDAO, - CassandraIndexTableHandler indexTableHandler, ModSeqProvider modSeqProvider, MailboxSession mailboxSession, CassandraConfiguration cassandraConfiguration) { + CassandraMessageIdToImapUidDAO imapUidDAO, CassandraMessageIdDAO messageIdDAO, + CassandraMessageDAO messageDAOV1, CassandraMessageDAOV2 messageDAOV2, + CassandraIndexTableHandler indexTableHandler, ModSeqProvider modSeqProvider, MailboxSession mailboxSession, + CassandraConfiguration cassandraConfiguration) { + this.mailboxMapper = mailboxMapper; this.mailboxDAO = mailboxDAO; this.imapUidDAO = imapUidDAO; this.messageIdDAO = messageIdDAO; - this.messageDAO = messageDAO; + this.messageDAOV2 = messageDAOV2; this.indexTableHandler = indexTableHandler; this.modSeqProvider = modSeqProvider; this.mailboxSession = mailboxSession; this.attachmentLoader = new AttachmentLoader(attachmentMapper); this.cassandraConfiguration = cassandraConfiguration; + this.v1ToV2Migration = new V1ToV2Migration(messageDAOV1, messageDAOV2, attachmentMapper); } @Override @@ -101,7 +110,7 @@ public class CassandraMessageIdMapper implements MessageIdMapper { .map(messageId -> imapUidDAO.retrieve((CassandraMessageId) messageId, Optional.empty()))) .thenApply(stream -> stream.flatMap(Function.identity())) .thenApply(stream -> stream.collect(Guavate.toImmutableList())) - .thenCompose(composedMessageIds -> messageDAO.retrieveMessages(composedMessageIds, fetchType, Optional.empty())) + .thenCompose(composedMessageIds -> retrieveMessages(fetchType, composedMessageIds)) .thenCompose(stream -> CompletableFutureUtil.allOf( stream.map(pair -> mailboxExists(pair.getLeft()) .thenApply(b -> Optional.of(pair).filter(any -> b))))) @@ -113,6 +122,14 @@ public class CassandraMessageIdMapper implements MessageIdMapper { .sorted(Comparator.comparing(MailboxMessage::getUid)); } + private CompletableFuture<Stream<Pair<MessageWithoutAttachment, Stream<MessageAttachmentRepresentation>>>> + retrieveMessages(FetchType fetchType, ImmutableList<ComposedMessageIdWithMetaData> composedMessageIds) { + return messageDAOV2.retrieveMessages(composedMessageIds, fetchType, Limit.unlimited()) + .thenCompose(messageResults -> FluentFutureStream.of(messageResults + .map(v1ToV2Migration::moveFromV1toV2)) + .completableFuture()); + } + private CompletableFuture<Boolean> mailboxExists(MessageWithoutAttachment messageWithoutAttachment) { CassandraId cassandraId = (CassandraId) messageWithoutAttachment.getMailboxId(); return mailboxDAO.retrieveMailbox(cassandraId) @@ -163,7 +180,7 @@ public class CassandraMessageIdMapper implements MessageIdMapper { .flags(mailboxMessage.createFlags()) .modSeq(mailboxMessage.getModSeq()) .build(); - messageDAO.save(mailboxMessage) + messageDAOV2.save(mailboxMessage) .thenCompose(voidValue -> CompletableFuture.allOf( imapUidDAO.insert(composedMessageIdWithMetaData), messageIdDAO.insert(composedMessageIdWithMetaData))) @@ -194,7 +211,6 @@ public class CassandraMessageIdMapper implements MessageIdMapper { public void delete(MessageId messageId) { CassandraMessageId cassandraMessageId = (CassandraMessageId) messageId; retrieveAndDeleteIndices(cassandraMessageId, Optional.empty()) - .thenCompose(voidValue -> messageDAO.delete(cassandraMessageId)) .join(); } http://git-wip-us.apache.org/repos/asf/james-project/blob/31567b21/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java index 55bf43d..6d716b7 100644 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java @@ -39,6 +39,8 @@ import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.MessageUid; import org.apache.james.mailbox.cassandra.CassandraId; import org.apache.james.mailbox.cassandra.CassandraMessageId; +import org.apache.james.mailbox.cassandra.Limit; +import org.apache.james.mailbox.cassandra.mail.migration.V1ToV2Migration; import org.apache.james.mailbox.cassandra.mail.utils.FlagsUpdateStageResult; import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.model.ComposedMessageId; @@ -73,7 +75,7 @@ public class CassandraMessageMapper implements MessageMapper { private final CassandraModSeqProvider modSeqProvider; private final MailboxSession mailboxSession; private final CassandraUidProvider uidProvider; - private final CassandraMessageDAO messageDAO; + private final CassandraMessageDAOV2 messageDAOV2; private final CassandraMessageIdDAO messageIdDAO; private final CassandraMessageIdToImapUidDAO imapUidDAO; private final CassandraMailboxCounterDAO mailboxCounterDAO; @@ -83,17 +85,21 @@ public class CassandraMessageMapper implements MessageMapper { private final CassandraFirstUnseenDAO firstUnseenDAO; private final AttachmentLoader attachmentLoader; private final CassandraDeletedMessageDAO deletedMessageDAO; + private final V1ToV2Migration v1ToV2Migration; private final CassandraConfiguration cassandraConfiguration; + + public CassandraMessageMapper(CassandraUidProvider uidProvider, CassandraModSeqProvider modSeqProvider, MailboxSession mailboxSession, CassandraAttachmentMapper attachmentMapper, - CassandraMessageDAO messageDAO, CassandraMessageIdDAO messageIdDAO, CassandraMessageIdToImapUidDAO imapUidDAO, + CassandraMessageDAO messageDAO, CassandraMessageDAOV2 messageDAOV2, + CassandraMessageIdDAO messageIdDAO, CassandraMessageIdToImapUidDAO imapUidDAO, CassandraMailboxCounterDAO mailboxCounterDAO, CassandraMailboxRecentsDAO mailboxRecentDAO, CassandraApplicableFlagDAO applicableFlagDAO, CassandraIndexTableHandler indexTableHandler, CassandraFirstUnseenDAO firstUnseenDAO, CassandraDeletedMessageDAO deletedMessageDAO, CassandraConfiguration cassandraConfiguration) { this.uidProvider = uidProvider; this.modSeqProvider = modSeqProvider; this.mailboxSession = mailboxSession; - this.messageDAO = messageDAO; + this.messageDAOV2 = messageDAOV2; this.messageIdDAO = messageIdDAO; this.imapUidDAO = imapUidDAO; this.mailboxCounterDAO = mailboxCounterDAO; @@ -103,6 +109,7 @@ public class CassandraMessageMapper implements MessageMapper { this.attachmentLoader = new AttachmentLoader(attachmentMapper); this.applicableFlagDAO = applicableFlagDAO; this.deletedMessageDAO = deletedMessageDAO; + this.v1ToV2Migration = new V1ToV2Migration(messageDAO, messageDAOV2, attachmentMapper); this.cassandraConfiguration = cassandraConfiguration; } @@ -169,7 +176,7 @@ public class CassandraMessageMapper implements MessageMapper { @Override public Iterator<MailboxMessage> findInMailbox(Mailbox mailbox, MessageRange messageRange, FetchType ftype, int max) throws MailboxException { CassandraId mailboxId = (CassandraId) mailbox.getMailboxId(); - return retrieveMessages(retrieveMessageIds(mailboxId, messageRange), ftype, Optional.of(max)) + return retrieveMessages(retrieveMessageIds(mailboxId, messageRange), ftype, Limit.from(max)) .join() .map(SimpleMailboxMessage -> (MailboxMessage) SimpleMailboxMessage) .sorted(Comparator.comparing(MailboxMessage::getUid)) @@ -182,21 +189,12 @@ public class CassandraMessageMapper implements MessageMapper { .collect(Guavate.toImmutableList()); } - private CompletableFuture<Stream<SimpleMailboxMessage>> retrieveMessages(List<ComposedMessageIdWithMetaData> messageIds, FetchType fetchType, Optional<Integer> limit) { - CompletableFuture<Stream<Pair<CassandraMessageDAO.MessageWithoutAttachment, Stream<CassandraMessageDAO.MessageAttachmentRepresentation>>>> - messageRepresentations = messageDAO.retrieveMessages(messageIds, fetchType, limit); + private CompletableFuture<Stream<SimpleMailboxMessage>> retrieveMessages(List<ComposedMessageIdWithMetaData> messageIds, FetchType fetchType, Limit limit) { + CompletableFuture<Stream<Pair<MessageWithoutAttachment, Stream<MessageAttachmentRepresentation>>>> + messageRepresentations = retrieveMessagesAndDoMigrationIfNeeded(messageIds, fetchType, limit); + if (fetchType == FetchType.Body || fetchType == FetchType.Full) { - return FluentFutureStream.of(messageRepresentations) - .thenComposeOnAll(pair -> - attachmentLoader.getAttachments(pair.getRight().collect(Guavate.toImmutableList())) - .thenApply(attachments -> Pair.of(pair.getLeft(), attachments)) - ) - .map(pair -> - pair.getLeft() - .toMailboxMessage(pair.getRight() - .stream() - .collect(Guavate.toImmutableList()))) - .completableFuture(); + return attachmentLoader.toMailboxMessageWithAttachments(messageRepresentations); } else { return FluentFutureStream.of(messageRepresentations) .map(pair -> @@ -207,6 +205,8 @@ public class CassandraMessageMapper implements MessageMapper { } } + + @Override public List<MessageUid> findRecentMessageUidsInMailbox(Mailbox mailbox) throws MailboxException { CassandraId mailboxId = (CassandraId) mailbox.getMailboxId(); @@ -240,12 +240,20 @@ public class CassandraMessageMapper implements MessageMapper { .map(uid -> messageIdDAO.retrieve(mailboxId, uid))) .flatMap(OptionalConverter::toStream) .performOnAll(this::deleteUsingMailboxId) - .thenComposeOnAll(idWithMetadata -> messageDAO.retrieveMessages(ImmutableList.of(idWithMetadata), FetchType.Metadata, Optional.empty())) + .thenComposeOnAll(idWithMetadata -> retrieveMessagesAndDoMigrationIfNeeded(ImmutableList.of(idWithMetadata), FetchType.Metadata, Limit.unlimited())) .flatMap(s -> s) .map(pair -> pair.getKey().toMailboxMessage(ImmutableList.of())) .completableFuture(); } + private CompletableFuture<Stream<Pair<MessageWithoutAttachment, Stream<MessageAttachmentRepresentation>>>> retrieveMessagesAndDoMigrationIfNeeded( + List<ComposedMessageIdWithMetaData> messageIds, FetchType fetchType, Limit limit) { + return messageDAOV2.retrieveMessages(messageIds, fetchType, limit) + .thenCompose(messageResults -> FluentFutureStream.of(messageResults + .map(v1ToV2Migration::moveFromV1toV2)) + .completableFuture()); + } + @Override public MessageMetaData move(Mailbox destinationMailbox, MailboxMessage original) throws MailboxException { CassandraId originalMailboxId = (CassandraId) original.getMailboxId(); @@ -377,7 +385,7 @@ public class CassandraMessageMapper implements MessageMapper { private CompletableFuture<Void> save(Mailbox mailbox, MailboxMessage message) throws MailboxException { CassandraId mailboxId = (CassandraId) mailbox.getMailboxId(); - return messageDAO.save(message) + return messageDAOV2.save(message) .thenCompose(aVoid -> insertIds(message, mailboxId)); } http://git-wip-us.apache.org/repos/asf/james-project/blob/31567b21/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MessageWithoutAttachment.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MessageWithoutAttachment.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MessageWithoutAttachment.java index e5bca7b..1c63cee 100644 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MessageWithoutAttachment.java +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MessageWithoutAttachment.java @@ -25,6 +25,8 @@ import javax.mail.Flags; import javax.mail.util.SharedByteArrayInputStream; import org.apache.james.mailbox.MessageUid; +import org.apache.james.mailbox.model.ComposedMessageId; +import org.apache.james.mailbox.model.ComposedMessageIdWithMetaData; import org.apache.james.mailbox.model.MailboxId; import org.apache.james.mailbox.model.MessageAttachment; import org.apache.james.mailbox.model.MessageId; @@ -73,7 +75,15 @@ public class MessageWithoutAttachment { return messageId; } + public ComposedMessageIdWithMetaData getMetadata() { + return new ComposedMessageIdWithMetaData(new ComposedMessageId(mailboxId, messageId, messageUid), flags, modSeq); + } + public SharedByteArrayInputStream getContent() { return content; } + + public PropertyBuilder getPropertyBuilder() { + return propertyBuilder; + } } http://git-wip-us.apache.org/repos/asf/james-project/blob/31567b21/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/V1ToV2Migration.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/V1ToV2Migration.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/V1ToV2Migration.java new file mode 100644 index 0000000..6ae6e4f --- /dev/null +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/V1ToV2Migration.java @@ -0,0 +1,90 @@ +/**************************************************************** + * 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.mail.migration; + +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.stream.Stream; + +import org.apache.commons.lang3.tuple.Pair; +import org.apache.james.mailbox.cassandra.CassandraMessageId; +import org.apache.james.mailbox.cassandra.Limit; +import org.apache.james.mailbox.cassandra.mail.AttachmentLoader; +import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentMapper; +import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAO; +import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAOV2; +import org.apache.james.mailbox.cassandra.mail.MessageAttachmentRepresentation; +import org.apache.james.mailbox.cassandra.mail.MessageWithoutAttachment; +import org.apache.james.mailbox.exception.MailboxException; +import org.apache.james.mailbox.model.ComposedMessageIdWithMetaData; +import org.apache.james.mailbox.store.mail.MessageMapper; +import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage; + +import com.google.common.collect.ImmutableList; + +public class V1ToV2Migration { + private final CassandraMessageDAO messageDAOV1; + private final CassandraMessageDAOV2 messageDAOV2; + private final AttachmentLoader attachmentLoader; + + public V1ToV2Migration(CassandraMessageDAO messageDAOV1, CassandraMessageDAOV2 messageDAOV2, CassandraAttachmentMapper attachmentMapper) { + this.messageDAOV1 = messageDAOV1; + this.messageDAOV2 = messageDAOV2; + this.attachmentLoader = new AttachmentLoader(attachmentMapper); + } + + public CompletableFuture<Pair<MessageWithoutAttachment, Stream<MessageAttachmentRepresentation>>> + moveFromV1toV2(CassandraMessageDAOV2.MessageResult result) { + + if (result.isFound()) { + return CompletableFuture.completedFuture(result.message()); + } + + return messageDAOV1.retrieveMessages(ImmutableList.of(result.getMetadata()), MessageMapper.FetchType.Full, Limit.unlimited()) + .thenApply(results -> results.findAny() + .orElseThrow(() -> new IllegalArgumentException("Message not found in DAO V1" + result.getMetadata()))) + .thenCompose(this::performV1ToV2Migration); + } + + private CompletableFuture<Pair<MessageWithoutAttachment, Stream<MessageAttachmentRepresentation>>> performV1ToV2Migration(Pair<MessageWithoutAttachment, Stream<MessageAttachmentRepresentation>> messageV1) { + return attachmentLoader.toMailboxMessageWithAttachments( + CompletableFuture.completedFuture(Stream.of(messageV1))) + .thenApply(stream -> stream.findAny().get()) + .thenCompose(this::saveInV2FromV1) + .thenCompose(this::deleteInV1) + .thenApply(any -> messageV1); + } + + private CompletableFuture<Void> deleteInV1(Optional<SimpleMailboxMessage> optional) { + return optional.map(SimpleMailboxMessage::getMessageId) + .map(messageId -> (CassandraMessageId) messageId) + .map(messageDAOV1::delete) + .orElse(CompletableFuture.completedFuture(null)); + } + + private CompletionStage<Optional<SimpleMailboxMessage>> saveInV2FromV1(SimpleMailboxMessage message) { + try { + return messageDAOV2.save(message).thenApply(any -> Optional.of(message)); + } catch (MailboxException e) { + return CompletableFuture.completedFuture(Optional.<SimpleMailboxMessage>empty()); + } + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/31567b21/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraMessageModule.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraMessageModule.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraMessageModule.java index 3a55d6f..db1bc58 100644 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraMessageModule.java +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraMessageModule.java @@ -112,8 +112,8 @@ public class CassandraMessageModule implements CassandraModule { .addColumn(CassandraMessageV2Table.BODY_OCTECTS, bigint()) .addColumn(CassandraMessageV2Table.TEXTUAL_LINE_COUNT, bigint()) .addColumn(CassandraMessageV2Table.FULL_CONTENT_OCTETS, bigint()) - .addColumn(CassandraMessageV2Table.BODY_CONTENT, timeuuid()) - .addColumn(CassandraMessageV2Table.HEADER_CONTENT, timeuuid()) + .addColumn(CassandraMessageV2Table.BODY_CONTENT, text()) + .addColumn(CassandraMessageV2Table.HEADER_CONTENT, text()) .addUDTListColumn(CassandraMessageV2Table.ATTACHMENTS, SchemaBuilder.frozen(CassandraMessageV2Table.ATTACHMENTS)) .addUDTListColumn(CassandraMessageV2Table.PROPERTIES, SchemaBuilder.frozen(CassandraMessageV2Table.PROPERTIES)))); types = ImmutableList.of( http://git-wip-us.apache.org/repos/asf/james-project/blob/31567b21/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerProvider.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerProvider.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerProvider.java index c34effb..7f02c9c 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerProvider.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerProvider.java @@ -25,6 +25,7 @@ import org.apache.james.mailbox.acl.MailboxACLResolver; import org.apache.james.mailbox.acl.SimpleGroupMembershipResolver; import org.apache.james.mailbox.acl.UnionMailboxACLResolver; import org.apache.james.mailbox.cassandra.mail.CassandraApplicableFlagDAO; +import org.apache.james.mailbox.cassandra.mail.CassandraBlobsDAO; import org.apache.james.mailbox.cassandra.mail.CassandraDeletedMessageDAO; import org.apache.james.mailbox.cassandra.mail.CassandraFirstUnseenDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMailboxCounterDAO; @@ -32,6 +33,7 @@ import org.apache.james.mailbox.cassandra.mail.CassandraMailboxDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMailboxPathDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMailboxRecentsDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAO; +import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAOV2; import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdToImapUidDAO; import org.apache.james.mailbox.cassandra.mail.CassandraModSeqProvider; @@ -55,7 +57,9 @@ public class CassandraMailboxManagerProvider { CassandraMessageId.Factory messageIdFactory = new CassandraMessageId.Factory(); CassandraMessageIdDAO messageIdDAO = new CassandraMessageIdDAO(session, messageIdFactory); CassandraMessageIdToImapUidDAO imapUidDAO = new CassandraMessageIdToImapUidDAO(session, messageIdFactory); + CassandraBlobsDAO blobsDAO = new CassandraBlobsDAO(session); CassandraMessageDAO messageDAO = new CassandraMessageDAO(session, cassandraTypesProvider); + CassandraMessageDAOV2 messageDAOV2 = new CassandraMessageDAOV2(session, cassandraTypesProvider, blobsDAO); CassandraMailboxCounterDAO mailboxCounterDAO = new CassandraMailboxCounterDAO(session); CassandraMailboxRecentsDAO mailboxRecentsDAO = new CassandraMailboxRecentsDAO(session); CassandraMailboxDAO mailboxDAO = new CassandraMailboxDAO(session, cassandraTypesProvider); @@ -68,6 +72,7 @@ public class CassandraMailboxManagerProvider { modSeqProvider, session, messageDAO, + messageDAOV2, messageIdDAO, imapUidDAO, mailboxCounterDAO, http://git-wip-us.apache.org/repos/asf/james-project/blob/31567b21/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerStressTest.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerStressTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerStressTest.java index 5ba536a..93ec3c9 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerStressTest.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerStressTest.java @@ -27,6 +27,7 @@ import org.apache.james.mailbox.cassandra.modules.CassandraAclModule; import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule; import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule; import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule; +import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule; import org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule; import org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule; import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule; @@ -45,6 +46,7 @@ public class CassandraMailboxManagerStressTest extends MailboxManagerStressTest new CassandraAclModule(), new CassandraMailboxModule(), new CassandraMessageModule(), + new CassandraBlobModule(), new CassandraMailboxCounterModule(), new CassandraMailboxRecentsModule(), new CassandraFirstUnseenModule(), http://git-wip-us.apache.org/repos/asf/james-project/blob/31567b21/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java index 271c163..9bc0934 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java @@ -26,6 +26,7 @@ import org.apache.james.mailbox.cassandra.modules.CassandraAclModule; import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule; import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule; import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule; +import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule; import org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule; import org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule; import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule; @@ -50,6 +51,7 @@ public class CassandraMailboxManagerTest extends MailboxManagerTest { new CassandraAclModule(), new CassandraMailboxModule(), new CassandraMessageModule(), + new CassandraBlobModule(), new CassandraMailboxCounterModule(), new CassandraMailboxRecentsModule(), new CassandraFirstUnseenModule(), http://git-wip-us.apache.org/repos/asf/james-project/blob/31567b21/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java index 0ae1dd6..c2c89bf 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java @@ -31,6 +31,7 @@ import org.apache.james.mailbox.cassandra.mail.CassandraMailboxDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMailboxPathDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMailboxRecentsDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAO; +import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAOV2; import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdToImapUidDAO; import org.apache.james.mailbox.cassandra.mail.CassandraModSeqProvider; @@ -68,6 +69,7 @@ public class CassandraSubscriptionManagerTest extends AbstractSubscriptionManage public SubscriptionManager createSubscriptionManager() { CassandraMessageIdToImapUidDAO imapUidDAO = null; CassandraMessageDAO messageDAO = null; + CassandraMessageDAOV2 messageDAOV2 = null; CassandraMessageIdDAO messageIdDAO = null; CassandraMailboxCounterDAO mailboxCounterDAO = null; CassandraMailboxRecentsDAO mailboxRecentsDAO = null; @@ -82,6 +84,7 @@ public class CassandraSubscriptionManagerTest extends AbstractSubscriptionManage new CassandraModSeqProvider(cassandra.getConf()), cassandra.getConf(), messageDAO, + messageDAOV2, messageIdDAO, imapUidDAO, mailboxCounterDAO, http://git-wip-us.apache.org/repos/asf/james-project/blob/31567b21/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java index a58b348..ea41086 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java @@ -23,6 +23,7 @@ import static org.mockito.Mockito.mock; import org.apache.james.backends.cassandra.CassandraCluster; import org.apache.james.backends.cassandra.init.CassandraModuleComposite; +import org.apache.james.mailbox.cassandra.mail.CassandraBlobsDAO; import org.apache.james.mailbox.cassandra.mail.CassandraDeletedMessageDAO; import org.apache.james.mailbox.cassandra.mail.CassandraFirstUnseenDAO; import org.apache.james.mailbox.cassandra.mail.CassandraApplicableFlagDAO; @@ -31,6 +32,7 @@ import org.apache.james.mailbox.cassandra.mail.CassandraMailboxDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMailboxPathDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMailboxRecentsDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAO; +import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAOV2; import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdToImapUidDAO; import org.apache.james.mailbox.cassandra.mail.CassandraModSeqProvider; @@ -39,6 +41,7 @@ import org.apache.james.mailbox.cassandra.modules.CassandraAclModule; import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule; import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule; import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule; +import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule; import org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule; import org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule; import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule; @@ -68,7 +71,9 @@ public class CassandraTestSystemFixture { CassandraMessageId.Factory messageIdFactory = new CassandraMessageId.Factory(); CassandraMessageIdDAO messageIdDAO = new CassandraMessageIdDAO(cassandra.getConf(), messageIdFactory); CassandraMessageIdToImapUidDAO imapUidDAO = new CassandraMessageIdToImapUidDAO(cassandra.getConf(), messageIdFactory); + CassandraBlobsDAO blobsDAO = new CassandraBlobsDAO(cassandra.getConf()); CassandraMessageDAO messageDAO = new CassandraMessageDAO(cassandra.getConf(), cassandra.getTypesProvider()); + CassandraMessageDAOV2 messageDAOV2 = new CassandraMessageDAOV2(cassandra.getConf(), cassandra.getTypesProvider(), blobsDAO); CassandraMailboxCounterDAO mailboxCounterDAO = new CassandraMailboxCounterDAO(cassandra.getConf()); CassandraMailboxRecentsDAO mailboxRecentsDAO = new CassandraMailboxRecentsDAO(cassandra.getConf()); CassandraApplicableFlagDAO applicableFlagDAO = new CassandraApplicableFlagDAO(cassandra.getConf()); @@ -81,6 +86,7 @@ public class CassandraTestSystemFixture { modSeqProvider, cassandra.getConf(), messageDAO, + messageDAOV2, messageIdDAO, imapUidDAO, mailboxCounterDAO, @@ -118,6 +124,7 @@ public class CassandraTestSystemFixture { new CassandraAclModule(), new CassandraMailboxModule(), new CassandraMessageModule(), + new CassandraBlobModule(), new CassandraMailboxCounterModule(), new CassandraMailboxRecentsModule(), new CassandraFirstUnseenModule(), http://git-wip-us.apache.org/repos/asf/james-project/blob/31567b21/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java index 722e7f7..d7c5097 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java @@ -31,6 +31,7 @@ import org.apache.james.mailbox.cassandra.CassandraMessageId; import org.apache.james.mailbox.cassandra.modules.CassandraAclModule; import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule; import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule; +import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule; import org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule; import org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule; import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule; @@ -59,6 +60,7 @@ public class CassandraMailboxManagerAttachmentTest extends AbstractMailboxManage new CassandraAclModule(), new CassandraMailboxModule(), new CassandraMessageModule(), + new CassandraBlobModule(), new CassandraMailboxCounterModule(), new CassandraMailboxRecentsModule(), new CassandraFirstUnseenModule(), @@ -85,11 +87,16 @@ public class CassandraMailboxManagerAttachmentTest extends AbstractMailboxManage CassandraMailboxPathDAO mailboxPathDAO = new CassandraMailboxPathDAO(cassandra.getConf(), cassandra.getTypesProvider()); CassandraFirstUnseenDAO firstUnseenDAO = new CassandraFirstUnseenDAO(cassandra.getConf()); CassandraDeletedMessageDAO deletedMessageDAO = new CassandraDeletedMessageDAO(cassandra.getConf()); + + CassandraBlobsDAO blobsDAO = new CassandraBlobsDAO(cassandra.getConf()); + CassandraMessageDAO messageDAO = new CassandraMessageDAO(cassandra.getConf(), cassandra.getTypesProvider()); + CassandraMessageDAOV2 messageDAOV2 = new CassandraMessageDAOV2(cassandra.getConf(), cassandra.getTypesProvider(), blobsDAO); mailboxSessionMapperFactory = new CassandraMailboxSessionMapperFactory( new CassandraUidProvider(cassandra.getConf()), new CassandraModSeqProvider(cassandra.getConf()), cassandra.getConf(), - new CassandraMessageDAO(cassandra.getConf(), cassandra.getTypesProvider()), + messageDAO, + messageDAOV2, new CassandraMessageIdDAO(cassandra.getConf(), messageIdFactory), new CassandraMessageIdToImapUidDAO(cassandra.getConf(), messageIdFactory), new CassandraMailboxCounterDAO(cassandra.getConf()), http://git-wip-us.apache.org/repos/asf/james-project/blob/31567b21/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMapperProvider.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMapperProvider.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMapperProvider.java index 74602f3..4357abe 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMapperProvider.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMapperProvider.java @@ -32,6 +32,7 @@ import org.apache.james.mailbox.cassandra.modules.CassandraAclModule; import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule; import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule; import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule; +import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule; import org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule; import org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule; import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule; @@ -79,7 +80,8 @@ public class CassandraMapperProvider implements MapperProvider { new CassandraAnnotationModule(), new CassandraFirstUnseenModule(), new CassandraApplicableFlagsModule(), - new CassandraDeletedMessageModule())); + new CassandraDeletedMessageModule(), + new CassandraBlobModule())); messageUidProvider = new MessageUidProvider(); cassandraModSeqProvider = new CassandraModSeqProvider(this.cassandra.getConf()); } @@ -109,11 +111,15 @@ public class CassandraMapperProvider implements MapperProvider { CassandraMailboxPathDAO mailboxPathDAO = new CassandraMailboxPathDAO(cassandra.getConf(), cassandra.getTypesProvider()); CassandraFirstUnseenDAO firstUnseenDAO = new CassandraFirstUnseenDAO(cassandra.getConf()); CassandraDeletedMessageDAO deletedMessageDAO = new CassandraDeletedMessageDAO(cassandra.getConf()); + CassandraBlobsDAO blobsDAO = new CassandraBlobsDAO(cassandra.getConf()); + CassandraMessageDAO messageDAO = new CassandraMessageDAO(cassandra.getConf(), cassandra.getTypesProvider()); + CassandraMessageDAOV2 messageDAOV2 = new CassandraMessageDAOV2(cassandra.getConf(), cassandra.getTypesProvider(), blobsDAO); return new CassandraMailboxSessionMapperFactory( new CassandraUidProvider(cassandra.getConf()), cassandraModSeqProvider, cassandra.getConf(), - new CassandraMessageDAO(cassandra.getConf(), cassandra.getTypesProvider()), + messageDAO, + messageDAOV2, new CassandraMessageIdDAO(cassandra.getConf(), MESSAGE_ID_FACTORY), new CassandraMessageIdToImapUidDAO(cassandra.getConf(), MESSAGE_ID_FACTORY), new CassandraMailboxCounterDAO(cassandra.getConf()), http://git-wip-us.apache.org/repos/asf/james-project/blob/31567b21/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java index 3f69d26..2ba82cc 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java @@ -29,6 +29,7 @@ import org.apache.james.backends.cassandra.CassandraCluster; import org.apache.james.mailbox.MessageUid; import org.apache.james.mailbox.cassandra.CassandraId; import org.apache.james.mailbox.cassandra.CassandraMessageId; +import org.apache.james.mailbox.cassandra.Limit; import org.apache.james.mailbox.cassandra.modules.CassandraMessageModule; import org.apache.james.mailbox.model.Attachment; import org.apache.james.mailbox.model.AttachmentId; @@ -106,7 +107,8 @@ public class CassandraMessageDAOTest { testee.save(messageWith1Attachment).join(); - List<Optional<MessageAttachmentRepresentation>> attachmentRepresentation = testee.retrieveMessages(messageIds, MessageMapper.FetchType.Body, Optional.empty()) + List<Optional<MessageAttachmentRepresentation>> attachmentRepresentation = + testee.retrieveMessages(messageIds, MessageMapper.FetchType.Body, Limit.unlimited()) .get() .map(pair -> pair.getRight()) .map(streamAttachemnt -> streamAttachemnt.findFirst()) @@ -128,7 +130,8 @@ public class CassandraMessageDAOTest { testee.save(messageWith1Attachment).join(); - List<Optional<MessageAttachmentRepresentation>> attachmentRepresentation = testee.retrieveMessages(messageIds, MessageMapper.FetchType.Body, Optional.empty()) + List<Optional<MessageAttachmentRepresentation>> attachmentRepresentation = + testee.retrieveMessages(messageIds, MessageMapper.FetchType.Body, Limit.unlimited()) .get() .map(pair -> pair.getRight()) .map(streamAttachemnt -> streamAttachemnt.findFirst()) @@ -138,8 +141,23 @@ public class CassandraMessageDAOTest { assertThat(attachmentRepresentation.get(0).get().getCid().isPresent()).isFalse(); } - private SimpleMailboxMessage createMessage(MessageId messageId, String content, int bodyStart, PropertyBuilder propertyBuilder, List<MessageAttachment> attachments) { - return new SimpleMailboxMessage(messageId, new Date(), content.length(), bodyStart, new SharedByteArrayInputStream(content.getBytes()), new Flags(), propertyBuilder, MAILBOX_ID, attachments); + private SimpleMailboxMessage createMessage( + MessageId messageId, + String content, + int bodyStart, + PropertyBuilder propertyBuilder, + List<MessageAttachment> attachments + ) { + return new SimpleMailboxMessage( + messageId, + new Date(), + content.length(), + bodyStart, + new SharedByteArrayInputStream(content.getBytes()), + new Flags(), + propertyBuilder, + MAILBOX_ID, + attachments); } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/31567b21/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/V1ToV2MigrationTest.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/V1ToV2MigrationTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/V1ToV2MigrationTest.java new file mode 100644 index 0000000..c1c505d --- /dev/null +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/V1ToV2MigrationTest.java @@ -0,0 +1,185 @@ +/**************************************************************** + * 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.mail.migration; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Date; +import java.util.List; +import java.util.Optional; + +import javax.mail.Flags; +import javax.mail.util.SharedByteArrayInputStream; + +import org.apache.commons.io.IOUtils; +import org.apache.james.backends.cassandra.CassandraCluster; +import org.apache.james.backends.cassandra.init.CassandraModuleComposite; +import org.apache.james.mailbox.MessageUid; +import org.apache.james.mailbox.cassandra.CassandraId; +import org.apache.james.mailbox.cassandra.CassandraMessageId; +import org.apache.james.mailbox.cassandra.Limit; +import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentMapper; +import org.apache.james.mailbox.cassandra.mail.CassandraBlobsDAO; +import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAO; +import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAOV2; +import org.apache.james.mailbox.cassandra.mail.MessageAttachmentRepresentation; +import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule; +import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule; +import org.apache.james.mailbox.cassandra.modules.CassandraMessageModule; +import org.apache.james.mailbox.model.Attachment; +import org.apache.james.mailbox.model.AttachmentId; +import org.apache.james.mailbox.model.Cid; +import org.apache.james.mailbox.model.ComposedMessageId; +import org.apache.james.mailbox.model.ComposedMessageIdWithMetaData; +import org.apache.james.mailbox.model.MessageAttachment; +import org.apache.james.mailbox.model.MessageId; +import org.apache.james.mailbox.store.mail.MessageMapper; +import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder; +import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage; +import org.apache.james.util.OptionalConverter; +import org.assertj.core.api.JUnitSoftAssertions; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import com.google.common.base.Charsets; +import com.google.common.collect.ImmutableList; + +public class V1ToV2MigrationTest { + private static final int BODY_START = 16; + private static final CassandraId MAILBOX_ID = CassandraId.timeBased(); + private static final String CONTENT = "Subject: Test7 \n\nBody7\n.\n"; + private static final MessageUid messageUid = MessageUid.of(1); + + private CassandraCluster cassandra; + + private CassandraMessageDAO messageDAOV1; + private CassandraMessageDAOV2 messageDAOV2; + private CassandraAttachmentMapper attachmentMapper; + private V1ToV2Migration testee; + + private Attachment attachment; + private CassandraMessageId messageId; + private CassandraMessageId.Factory messageIdFactory; + private ComposedMessageId composedMessageId; + private List<ComposedMessageIdWithMetaData> metaDataList; + private ComposedMessageIdWithMetaData metaData; + private MessageAttachment messageAttachment; + + @Rule + public final JUnitSoftAssertions softly = new JUnitSoftAssertions(); + + @Before + public void setUp() { + cassandra = CassandraCluster.create(new CassandraModuleComposite( + new CassandraMessageModule(), + new CassandraBlobModule(), + new CassandraAttachmentModule())); + cassandra.ensureAllTables(); + + messageDAOV1 = new CassandraMessageDAO(cassandra.getConf(), cassandra.getTypesProvider()); + CassandraBlobsDAO blobsDAO = new CassandraBlobsDAO(cassandra.getConf()); + messageDAOV2 = new CassandraMessageDAOV2(cassandra.getConf(), cassandra.getTypesProvider(), blobsDAO); + attachmentMapper = new CassandraAttachmentMapper(cassandra.getConf()); + testee = new V1ToV2Migration(messageDAOV1, messageDAOV2, attachmentMapper); + + + messageIdFactory = new CassandraMessageId.Factory(); + messageId = messageIdFactory.generate(); + + attachment = Attachment.builder() + .attachmentId(AttachmentId.from("123")) + .bytes("attachment".getBytes()) + .type("content") + .build(); + + composedMessageId = new ComposedMessageId(MAILBOX_ID, messageId, messageUid); + + metaData = ComposedMessageIdWithMetaData.builder() + .composedMessageId(composedMessageId) + .flags(new Flags()) + .modSeq(1) + .build(); + metaDataList = ImmutableList.of(metaData); + messageAttachment = MessageAttachment.builder() + .attachment(attachment) + .cid(Cid.from("<cid>")) + .isInline(true) + .name("toto.png") + .build(); + } + + @After + public void tearDown() { + cassandra.clearAllTables(); + cassandra.close(); + } + + @Test + public void migrationShouldWorkWithoutAttachments() throws Exception { + SimpleMailboxMessage originalMessage = createMessage(messageId, CONTENT, BODY_START, + new PropertyBuilder(), ImmutableList.of()); + messageDAOV1.save(originalMessage).join(); + + testee.moveFromV1toV2(CassandraMessageDAOV2.notFound(metaData)).join(); + + Optional<CassandraMessageDAOV2.MessageResult> messageResult = messageDAOV2.retrieveMessages(metaDataList, MessageMapper.FetchType.Full, Limit.unlimited()) + .join() + .findAny(); + + assertThat(messageResult.isPresent()).isTrue(); + softly.assertThat(messageResult.get().message().getLeft().getMessageId()).isEqualTo(messageId); + softly.assertThat(IOUtils.toString(messageResult.get().message().getLeft().getContent(), Charsets.UTF_8)) + .isEqualTo(CONTENT); + softly.assertThat(messageResult.get().message().getRight().findAny().isPresent()).isFalse(); + } + + @Test + public void migrationShouldWorkWithAttachments() throws Exception { + SimpleMailboxMessage originalMessage = createMessage(messageId, CONTENT, BODY_START, + new PropertyBuilder(), ImmutableList.of(messageAttachment)); + + attachmentMapper.storeAttachment(attachment); + + messageDAOV1.save(originalMessage).join(); + + testee.moveFromV1toV2(CassandraMessageDAOV2.notFound(metaData)).join(); + + Optional<CassandraMessageDAOV2.MessageResult> messageResult = messageDAOV2.retrieveMessages(metaDataList, MessageMapper.FetchType.Full, Limit.unlimited()) + .join() + .findAny(); + + assertThat(messageResult.isPresent()).isTrue(); + softly.assertThat(messageResult.get().message().getLeft().getMessageId()).isEqualTo(messageId); + softly.assertThat(IOUtils.toString(messageResult.get().message().getLeft().getContent(), Charsets.UTF_8)) + .isEqualTo(CONTENT); + softly.assertThat(messageResult.get().message().getRight().findAny().get()).isEqualTo(MessageAttachmentRepresentation.builder() + .attachmentId(attachment.getAttachmentId()) + .cid(OptionalConverter.fromGuava(messageAttachment.getCid())) + .isInline(messageAttachment.isInline()) + .name(messageAttachment.getName().get()) + .build()); + } + + private SimpleMailboxMessage createMessage(MessageId messageId, String content, int bodyStart, PropertyBuilder propertyBuilder, List<MessageAttachment> attachments) { + return new SimpleMailboxMessage(messageId, new Date(), content.length(), bodyStart, new SharedByteArrayInputStream(content.getBytes()), new Flags(), propertyBuilder, MAILBOX_ID, attachments); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/31567b21/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java ---------------------------------------------------------------------- diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java index 6e9e1b5..215a846 100644 --- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java +++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java @@ -286,6 +286,15 @@ public abstract class MessageMapperTest { } @Test + public void messagesRetrievedUsingFetchTypeFullShouldHaveBodyDataLoaded() throws MailboxException, IOException{ + saveMessages(); + MessageMapper.FetchType fetchType = FetchType.Full; + Iterator<MailboxMessage> retrievedMessageIterator = messageMapper.findInMailbox(benwaInboxMailbox, MessageRange.one(message1.getUid()), fetchType, LIMIT); + assertThat(retrievedMessageIterator.next()).isEqualToWithoutAttachment(message1, fetchType); + assertThat(retrievedMessageIterator).isEmpty(); + } + + @Test public void retrievingMessagesWithALimitShouldLimitTheNumberOfMessages() throws MailboxException { int limit = 2; saveMessages(); http://git-wip-us.apache.org/repos/asf/james-project/blob/31567b21/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java ---------------------------------------------------------------------- diff --git a/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java b/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java index 9a9077a..d191bb1 100644 --- a/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java +++ b/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java @@ -29,6 +29,7 @@ import org.apache.james.mailbox.SubscriptionManager; import org.apache.james.mailbox.cassandra.CassandraMailboxManager; import org.apache.james.mailbox.cassandra.CassandraMailboxSessionMapperFactory; import org.apache.james.mailbox.cassandra.CassandraMessageId; +import org.apache.james.mailbox.cassandra.mail.CassandraBlobsDAO; import org.apache.james.mailbox.cassandra.mail.CassandraDeletedMessageDAO; import org.apache.james.mailbox.cassandra.mail.CassandraFirstUnseenDAO; import org.apache.james.mailbox.cassandra.mail.CassandraApplicableFlagDAO; @@ -37,6 +38,7 @@ import org.apache.james.mailbox.cassandra.mail.CassandraMailboxDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMailboxPathDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMailboxRecentsDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAO; +import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAOV2; import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdToImapUidDAO; import org.apache.james.mailbox.cassandra.mail.CassandraModSeqProvider; @@ -45,6 +47,7 @@ import org.apache.james.mailbox.cassandra.modules.CassandraAclModule; import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule; import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule; import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule; +import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule; import org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule; import org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule; import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule; @@ -89,6 +92,7 @@ public class CassandraHostSystem extends JamesImapHostSystem { new CassandraAclModule(), new CassandraMailboxModule(), new CassandraMessageModule(), + new CassandraBlobModule(), new CassandraMailboxCounterModule(), new CassandraMailboxRecentsModule(), new CassandraFirstUnseenModule(), @@ -107,6 +111,8 @@ public class CassandraHostSystem extends JamesImapHostSystem { CassandraTypesProvider typesProvider = new CassandraTypesProvider(mailboxModule, session); CassandraMessageId.Factory messageIdFactory = new CassandraMessageId.Factory(); CassandraMessageDAO messageDAO = new CassandraMessageDAO(session, typesProvider); + CassandraBlobsDAO cassandraBlobDao = new CassandraBlobsDAO(session); + CassandraMessageDAOV2 messageDAOV2 = new CassandraMessageDAOV2(session, typesProvider, cassandraBlobDao); CassandraMessageIdDAO messageIdDAO = new CassandraMessageIdDAO(session, messageIdFactory); CassandraMessageIdToImapUidDAO imapUidDAO = new CassandraMessageIdToImapUidDAO(session, messageIdFactory); CassandraMailboxCounterDAO mailboxCounterDAO = new CassandraMailboxCounterDAO(session); @@ -122,6 +128,7 @@ public class CassandraHostSystem extends JamesImapHostSystem { modSeqProvider, session, messageDAO, + messageDAOV2, messageIdDAO, imapUidDAO, mailboxCounterDAO, http://git-wip-us.apache.org/repos/asf/james-project/blob/31567b21/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java ---------------------------------------------------------------------- diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java index 78221b7..d45cbc0 100644 --- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java +++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java @@ -116,6 +116,7 @@ public class CassandraMailboxModule extends AbstractModule { cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule.class); cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraMailboxModule.class); cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraMessageModule.class); + cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraBlobModule.class); cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraSubscriptionModule.class); cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraUidModule.class); cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraModSeqModule.class); --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org