use of com.zimbra.cs.store.StoreManager in project zm-mailbox by Zimbra.
the class TestStoreManager method testStore.
@Test
public void testStore() throws Exception {
ParsedMessage pm = getMessage();
byte[] mimeBytes = TestUtil.readInputStream(pm.getRawInputStream());
Mailbox mbox = TestUtil.getMailbox(USER_NAME);
StoreManager sm = StoreManager.getInstance();
Blob blob = sm.storeIncoming(pm.getRawInputStream());
Assert.assertEquals("blob size = message size", pm.getRawData().length, blob.getRawSize());
Assert.assertTrue("blob content = mime content", TestUtil.bytesEqual(mimeBytes, blob.getInputStream()));
StagedBlob staged = sm.stage(blob, mbox);
Assert.assertEquals("staged size = blob size", blob.getRawSize(), staged.getSize());
MailboxBlob mblob = sm.link(staged, mbox, 0, 0);
Assert.assertEquals("link size = staged size", staged.getSize(), mblob.getSize());
Assert.assertTrue("link content = mime content", TestUtil.bytesEqual(mimeBytes, mblob.getLocalBlob().getInputStream()));
mblob = sm.getMailboxBlob(mbox, 0, 0, staged.getLocator());
Assert.assertEquals("mblob size = staged size", staged.getSize(), mblob.getSize());
Assert.assertTrue("mailboxblob content = mime content", TestUtil.bytesEqual(mimeBytes, mblob.getLocalBlob().getInputStream()));
}
use of com.zimbra.cs.store.StoreManager in project zm-mailbox by Zimbra.
the class Mailbox method saveDraft.
/**
* Saves draft.
*
* @param autoSendTime time at which the draft needs to be auto-sent. Note that this method does not schedule
* the task for auto-sending the draft. It just persists this time for tracking purposes.
* @see com.zimbra.cs.service.mail.SaveDraft#handle(com.zimbra.common.soap.Element, java.util.Map)
*/
public Message saveDraft(OperationContext octxt, ParsedMessage pm, int id, String origId, String replyType, String identityId, String accountId, long autoSendTime) throws IOException, ServiceException {
Message.DraftInfo dinfo = null;
if ((replyType != null && origId != null) || identityId != null || accountId != null || autoSendTime != 0) {
dinfo = new Message.DraftInfo(replyType, origId, identityId, accountId, autoSendTime);
}
if (id == ID_AUTO_INCREMENT) {
// special-case saving a new draft
return addMessage(octxt, pm, ID_FOLDER_DRAFTS, true, Flag.BITMASK_DRAFT | Flag.BITMASK_FROM_ME, null, ID_AUTO_INCREMENT, ":API:", dinfo, null, null);
}
// write the draft content directly to the mailbox's blob staging area
StoreManager sm = StoreManager.getInstance();
StagedBlob staged;
InputStream is = pm.getRawInputStream();
try {
staged = sm.stage(is, this);
} finally {
ByteUtil.closeStream(is);
}
String digest = staged.getDigest();
int size = (int) staged.getSize();
SaveDraft redoRecorder = new SaveDraft(mId, id, digest, size);
InputStream redoStream = null;
boolean success = false;
try {
beginTransaction("saveDraft", octxt, redoRecorder);
SaveDraft redoPlayer = (SaveDraft) currentChange().getRedoPlayer();
Message msg = getMessageById(id);
if (!msg.isTagged(Flag.FlagInfo.DRAFT)) {
throw MailServiceException.IMMUTABLE_OBJECT(id);
}
if (!checkItemChangeID(msg)) {
throw MailServiceException.MODIFY_CONFLICT();
}
// content changed, so we're obliged to change the IMAP uid
int imapID = getNextItemId(redoPlayer == null ? ID_AUTO_INCREMENT : redoPlayer.getImapId());
redoRecorder.setImapId(imapID);
redoRecorder.setMessageBodyInfo(new ParsedMessageDataSource(pm), size);
msg.setDraftAutoSendTime(autoSendTime);
if (dinfo != null) {
if (replyType != null) {
msg.setDraftReplyType(replyType);
}
if (origId != null) {
msg.setDraftOrigId(origId);
}
if (identityId != null) {
msg.setDraftIdentityId(identityId);
}
if (accountId != null) {
msg.setDraftAccountId(accountId);
}
if (autoSendTime != 0) {
msg.setDraftAutoSendTime(autoSendTime);
}
}
// update the content and increment the revision number
msg.setContent(staged, pm);
index.add(msg);
success = true;
try {
Notification.getInstance().interceptIfNecessary(this, pm.getMimeMessage(), "save draft", msg.getFolder());
} catch (ServiceException e) {
ZimbraLog.mailbox.error("Unable to send lawful intercept message.", e);
}
return msg;
} finally {
endTransaction(success);
ByteUtil.closeStream(redoStream);
sm.quietDelete(staged);
}
}
use of com.zimbra.cs.store.StoreManager in project zm-mailbox by Zimbra.
the class Mailbox method addDocumentRevision.
public Document addDocumentRevision(OperationContext octxt, int docId, ParsedDocument pd) throws IOException, ServiceException {
StoreManager sm = StoreManager.getInstance();
StagedBlob staged = sm.stage(pd.getBlob(), this);
AddDocumentRevision redoRecorder = new AddDocumentRevision(mId, pd.getDigest(), pd.getSize(), 0);
boolean success = false;
try {
beginTransaction("addDocumentRevision", octxt, redoRecorder);
Document doc = getDocumentById(docId);
redoRecorder.setDocument(pd);
redoRecorder.setDocId(docId);
redoRecorder.setItemType(doc.getType());
// TODO: simplify the redoRecorder by not subclassing from CreateMessage
// Get the redolog data from the mailbox blob. This is less than ideal in the
// HTTP store case because it will result in network access, and possibly an
// extra write to local disk. If this becomes a problem, we should update the
// ParsedDocument constructor to take a DataSource instead of an InputStream.
MailboxBlob mailboxBlob = doc.setContent(staged, pd);
redoRecorder.setMessageBodyInfo(new MailboxBlobDataSource(mailboxBlob), mailboxBlob.getSize());
index.add(doc);
success = true;
return doc;
} catch (IOException ioe) {
throw ServiceException.FAILURE("error writing document blob", ioe);
} finally {
endTransaction(success);
sm.quietDelete(staged);
}
}
use of com.zimbra.cs.store.StoreManager in project zm-mailbox by Zimbra.
the class AbstractExternalStoreManagerTest method testUncachedFile.
@Test
public void testUncachedFile() throws Exception {
ParsedMessage pm = ThreaderTest.getRootMessage();
byte[] mimeBytes = TestUtil.readInputStream(pm.getRawInputStream());
Mailbox mbox = MailboxManager.getInstance().getMailboxByAccountId(MockProvisioning.DEFAULT_ACCOUNT_ID);
StoreManager sm = StoreManager.getInstance();
Blob blob = sm.storeIncoming(pm.getRawInputStream());
StagedBlob staged = sm.stage(blob, mbox);
MailboxBlob mblob = sm.link(staged, mbox, 0, 0);
mblob = sm.getMailboxBlob(mbox, 0, 0, staged.getLocator());
Blob localBlob = mblob.getLocalBlob();
InputStream stream = sm.getContent(localBlob);
Assert.assertTrue("input stream external", stream instanceof BlobInputStream);
if (sm instanceof ExternalStoreManager) {
((ExternalStoreManager) sm).clearCache();
}
blob.getFile().delete();
Assert.assertFalse(blob.getFile().exists());
//now get it again. this would bomb if it only looked in cache
stream = sm.getContent(mblob.getLocalBlob());
Assert.assertTrue("input stream external", stream instanceof ExternalBlobInputStream);
ExternalBlobInputStream extStream = (ExternalBlobInputStream) stream;
File file = extStream.getRootFile();
Assert.assertTrue(file.exists());
Assert.assertTrue("stream content = mime content", TestUtil.bytesEqual(mimeBytes, stream));
}
use of com.zimbra.cs.store.StoreManager in project zm-mailbox by Zimbra.
the class DbMailItem method accumulateLeafNodes.
/**
* Accumulates <tt>PendingDelete</tt> info for the given <tt>ResultSet</tt>.
* @return a <tt>List</tt> of all versioned items, to be used in a subsequent call to
* {@link DbMailItem#accumulateLeafRevisions}, or an empty list.
*/
static List<Integer> accumulateLeafNodes(PendingDelete info, Mailbox mbox, ResultSet rs) throws SQLException, ServiceException {
boolean dumpsterEnabled = mbox.dumpsterEnabled();
boolean useDumpsterForSpam = mbox.useDumpsterForSpam();
StoreManager sm = StoreManager.getInstance();
List<Integer> versioned = new ArrayList<Integer>();
while (rs.next()) {
// first check to make sure we don't have a modify conflict
int revision = rs.getInt(LEAF_CI_MOD_CONTENT);
int modMetadata = rs.getInt(LEAF_CI_MOD_METADATA);
if (!mbox.checkItemChangeID(modMetadata, revision)) {
info.incomplete = true;
continue;
}
int id = rs.getInt(LEAF_CI_ID);
String uuid = rs.getString(LEAF_CI_UUID);
long size = rs.getLong(LEAF_CI_SIZE);
MailItem.Type type = MailItem.Type.of(rs.getByte(LEAF_CI_TYPE));
Integer itemId = Integer.valueOf(id);
info.itemIds.add(type, itemId, uuid);
info.size += size;
if (rs.getBoolean(LEAF_CI_IS_UNREAD)) {
info.unreadIds.add(itemId);
}
boolean isMessage = false;
switch(type) {
case CONTACT:
info.contacts++;
break;
case CHAT:
case MESSAGE:
isMessage = true;
break;
}
// record deleted virtual conversations and modified-or-deleted real conversations
if (isMessage) {
int parentId = rs.getInt(LEAF_CI_PARENT_ID);
if (rs.wasNull() || parentId <= 0) {
// conversations don't have UUIDs, so this is safe
info.itemIds.add(MailItem.Type.VIRTUAL_CONVERSATION, -id, null);
} else {
info.modifiedIds.add(parentId);
}
}
int flags = rs.getInt(LEAF_CI_FLAGS);
if ((flags & Flag.BITMASK_VERSIONED) != 0) {
versioned.add(id);
}
Integer folderId = rs.getInt(LEAF_CI_FOLDER_ID);
boolean isDeleted = (flags & Flag.BITMASK_DELETED) != 0;
LocationCount fcount = info.folderCounts.get(folderId);
if (fcount == null) {
info.folderCounts.put(folderId, new LocationCount(1, isDeleted ? 1 : 0, size));
} else {
fcount.increment(1, isDeleted ? 1 : 0, size);
}
String[] tags = DbTag.deserializeTags(rs.getString(LEAF_CI_TAGS));
if (tags != null) {
for (String tag : tags) {
LocationCount tcount = info.tagCounts.get(tag);
if (tcount == null) {
info.tagCounts.put(tag, new LocationCount(1, isDeleted ? 1 : 0, size));
} else {
tcount.increment(1, isDeleted ? 1 : 0, size);
}
}
}
int fid = folderId != null ? folderId.intValue() : -1;
if (!dumpsterEnabled || fid == Mailbox.ID_FOLDER_DRAFTS || (fid == Mailbox.ID_FOLDER_SPAM && !useDumpsterForSpam)) {
String blobDigest = rs.getString(LEAF_CI_BLOB_DIGEST);
if (blobDigest != null) {
info.blobDigests.add(blobDigest);
String locator = rs.getString(LEAF_CI_LOCATOR);
try {
MailboxBlob mblob = sm.getMailboxBlob(mbox, id, revision, locator, false);
if (mblob == null) {
ZimbraLog.mailbox.warn("missing blob for id: %d, change: %d", id, revision);
} else {
info.blobs.add(mblob);
}
} catch (Exception e1) {
ZimbraLog.mailbox.warn("Exception while getting mailbox blob", e1);
}
}
int indexId = rs.getInt(LEAF_CI_INDEX_ID);
boolean indexed = !rs.wasNull();
if (indexed) {
if (info.sharedIndex == null) {
info.sharedIndex = new HashSet<Integer>();
}
boolean shared = (flags & Flag.BITMASK_COPIED) != 0;
if (shared) {
info.sharedIndex.add(indexId);
} else {
info.indexIds.add(indexId > MailItem.IndexStatus.STALE.id() ? indexId : id);
}
}
}
}
return versioned;
}
Aggregations