use of com.zimbra.cs.store.MailboxBlob in project zm-mailbox by Zimbra.
the class ExternalStoreManager method renameTo.
@Override
public MailboxBlob renameTo(StagedBlob src, Mailbox destMbox, int destMsgId, int destRevision) throws IOException, ServiceException {
// rename is a noop
ExternalStagedBlob staged = (ExternalStagedBlob) src;
staged.markInserted();
MailboxBlob mblob = new ExternalMailboxBlob(destMbox, destMsgId, destRevision, staged.getLocator());
return mblob.setSize(staged.getSize()).setDigest(staged.getDigest());
}
use of com.zimbra.cs.store.MailboxBlob in project zm-mailbox by Zimbra.
the class ExternalBlobConsistencyChecker method checkExternalBlob.
private void checkExternalBlob(Mailbox mbox, boolean checkSize, BlobInfo blobInfo, ExternalStoreManager sm) throws ServiceException {
MailboxBlob mblob = sm.getMailboxBlob(mbox, blobInfo.itemId, blobInfo.version, blobInfo.path, false);
if (mblob == null) {
results.missingBlobs.put(blobInfo.itemId, blobInfo);
} else {
try {
unexpectedBlobPaths.remove(mblob.getLocator());
Blob blob = sm.getLocalBlob(mbox, mblob.getLocator(), false);
if (blob == null) {
results.missingBlobs.put(blobInfo.itemId, blobInfo);
} else {
//blob exists for the locator
blobInfo.fileModContent = blobInfo.modContent;
if (reportUsedBlobs) {
results.usedBlobs.put(blobInfo.itemId, blobInfo);
}
if (checkSize) {
blobInfo.fileSize = blob.getFile().length();
blobInfo.fileDataSize = getDataSize(blob.getFile(), blobInfo.dbSize);
if (blobInfo.dbSize != blobInfo.fileDataSize) {
results.incorrectSize.put(blobInfo.itemId, blobInfo);
}
}
}
} catch (Exception e) {
blobInfo.fetchException = e instanceof IOException ? (IOException) e : new IOException("Exception fetching blob", e);
results.missingBlobs.put(blobInfo.itemId, blobInfo);
}
}
}
use of com.zimbra.cs.store.MailboxBlob in project zm-mailbox by Zimbra.
the class Mailbox method endTransaction.
/**
* Be very careful when changing code in this method. The order of almost
* every line of code is important to ensure correct redo logging and crash
* recovery.
*
* @param success true to commit the transaction, false to rollback
* @throws ServiceException error
*/
protected void endTransaction(boolean success) throws ServiceException {
assert !Thread.holdsLock(this) : "Use MailboxLock";
if (lock.isUnlocked()) {
ZimbraLog.mailbox.warn("transaction canceled because of lock failure");
assert (!success);
return;
}
// blob and index to delete
PendingDelete deletes = null;
// blob to delete for failure cases
List<Object> rollbackDeletes = null;
try {
if (!currentChange().isActive()) {
// would like to throw here, but it might cover another
// exception...
ZimbraLog.mailbox.warn("cannot end a transaction when not inside a transaction", new Exception());
return;
}
if (!currentChange().endChange()) {
return;
}
ServiceException exception = null;
if (success) {
List<IndexItemEntry> indexItems = currentChange().indexItems;
if (!indexItems.isEmpty()) {
assert (currentChange().writeChange);
//TODO: See bug 15072 - we need to clear mCurrentChange.indexItems (it is stored in a temporary) here,
// just in case item.reindex() recurses into a new transaction...
currentChange().indexItems = new ArrayList<IndexItemEntry>();
index.add(indexItems);
}
// update mailbox size, folder unread/message counts
try {
snapshotCounts();
} catch (ServiceException e) {
exception = e;
success = false;
}
}
DbConnection conn = currentChange().conn;
// transaction, so no redo cleanup is necessary.
if (!success) {
DbPool.quietRollback(conn);
rollbackDeletes = rollbackCache(currentChange());
if (exception != null) {
throw exception;
}
return;
}
RedoableOp redoRecorder = currentChange().recorder;
boolean needRedo = needRedo(currentChange().octxt, redoRecorder);
// Log the change redo record for main transaction.
if (redoRecorder != null && needRedo) {
redoRecorder.log(true);
}
boolean dbCommitSuccess = false;
try {
// Commit the main transaction in database.
if (conn != null) {
try {
conn.commit();
} catch (Throwable t) {
// Any exception during database commit is a disaster
// because we don't know if the change is committed or
// not. Force the server to abort. Next restart will
// redo the operation to ensure the change is made and
// committed. (bug 2121)
Zimbra.halt("Unable to commit database transaction. Forcing server to abort.", t);
}
}
dbCommitSuccess = true;
} finally {
if (!dbCommitSuccess) {
// recovery will try to redo the operation.
if (needRedo) {
if (redoRecorder != null) {
redoRecorder.abort();
}
}
DbPool.quietRollback(conn);
rollbackDeletes = rollbackCache(currentChange());
return;
}
}
if (needRedo) {
// case would result in a redo error, and the second case would index the wrong value.
if (redoRecorder != null) {
if (currentChange().dirty != null && !currentChange().dirty.changedTypes.isEmpty()) {
// if an "all accounts" waitset is active, and this change has an appropriate type,
// then we'll need to set a commit-callback
AllAccountsRedoCommitCallback cb = AllAccountsRedoCommitCallback.getRedoCallbackIfNecessary(getAccountId(), currentChange().dirty.changedTypes);
if (cb != null) {
redoRecorder.setCommitCallback(cb);
}
}
redoRecorder.commit();
}
}
boolean changeMade = currentChange().changeId != MailboxChange.NO_CHANGE;
// keep a reference for cleanup
deletes = currentChange().deletes;
// deletes outside the lock
// We are finally done with database and redo commits. Cache update
// comes last.
commitCache(currentChange());
// down in its call stack.
if (changeMade) {
index.maybeIndexDeferredItems();
}
} finally {
lock.release();
// entail a blocking network operation
if (deletes != null) {
if (!deletes.indexIds.isEmpty()) {
// delete any index entries associated with items deleted from db
index.delete(deletes.indexIds);
}
if (deletes.blobs != null) {
// delete any blobs associated with items deleted from db/index
StoreManager sm = StoreManager.getInstance();
for (MailboxBlob blob : deletes.blobs) {
sm.quietDelete(blob);
}
}
}
if (rollbackDeletes != null) {
StoreManager sm = StoreManager.getInstance();
for (Object obj : rollbackDeletes) {
if (obj instanceof MailboxBlob) {
sm.quietDelete((MailboxBlob) obj);
} else if (obj instanceof Blob) {
sm.quietDelete((Blob) obj);
}
}
}
}
}
use of com.zimbra.cs.store.MailboxBlob in project zm-mailbox by Zimbra.
the class WikiDigestFixup method getWikiDigests.
private static List<WikiDigest> getWikiDigests(int mboxId) throws IOException, ServiceException {
Mailbox mbox = null;
try {
mbox = MailboxManager.getInstance().getMailboxById(mboxId);
} catch (ServiceException e) {
String code = e.getCode();
if (AccountServiceException.NO_SUCH_ACCOUNT.equals(code) || ServiceException.WRONG_HOST.equals(code))
return null;
else
throw e;
}
OperationContext octxt = new OperationContext(mbox);
List<MailItem> items = new ArrayList<MailItem>();
List<MailItem> wikis = mbox.getItemList(octxt, MailItem.Type.WIKI);
if (wikis != null && wikis.size() > 0)
items.addAll(wikis);
List<MailItem> documents = mbox.getItemList(octxt, MailItem.Type.DOCUMENT);
if (documents != null && documents.size() > 0)
items.addAll(documents);
int len = items.size();
List<WikiDigest> list = new ArrayList<WikiDigest>(len);
if (len > 0) {
for (MailItem item : items) {
// didn't support >2GB wiki items when the bug was occurring
if (item.getSize() > Integer.MAX_VALUE)
continue;
int id = item.getId();
MailboxBlob blob = sStore.getMailboxBlob(item);
InputStream is = null;
try {
is = sStore.getContent(blob);
byte[] data = ByteUtil.getContent(is, (int) item.getSize());
String digest = ByteUtil.getSHA1Digest(data, true);
String currentDigest = item.getDigest();
if (!digest.equals(currentDigest)) {
System.out.println("Found id " + id + ", current digest = \"" + currentDigest + "\"");
WikiDigest wd = new WikiDigest(mboxId, id, digest);
list.add(wd);
} else {
System.out.println("Found id " + id + " but skipping because digest is correct.");
}
} finally {
ByteUtil.closeStream(is);
}
}
}
return list;
}
use of com.zimbra.cs.store.MailboxBlob 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()));
}
Aggregations