public void forceDeleteMailbox(Mailbox mbox) throws ServiceException { DeleteMailbox redoRecorder = new DeleteMailbox(mbox.getId()); boolean success = false; try { beginTransaction("deleteMailbox", null, redoRecorder); redoRecorder.log(); try { // remove all the relevant entries from the database DbConnection conn = getOperationConnection(); ZimbraLog.mailbox.info( "attempting to remove the zimbra.mailbox row for id " + mbox.getId()); DbOfflineMailbox.forceDeleteMailbox(conn, mbox.getId()); success = true; } finally { // commit the DB transaction before touching the store! (also ends the operation) endTransaction(success); } if (success) { // remove all traces of the mailbox from the Mailbox cache // (so anyone asking for the Mailbox gets NO_SUCH_MBOX or creates a fresh new empty one // with a different id) MailboxManager.getInstance().markMailboxDeleted(mbox); } } finally { if (success) { redoRecorder.commit(); } else { redoRecorder.abort(); } } }
@Override public CalendarItem getCalendarItemByUid(OperationContext octxt, String uid) throws ServiceException { lock.lock(); try { CalendarItem item = super.getCalendarItemByUid(octxt, uid); if (item == null && Db.supports(Capability.CASE_SENSITIVE_COMPARISON) && Invite.isOutlookUid(uid)) { if (!uid.toLowerCase().equals(uid)) { // maybe stored in db in lower case item = super.getCalendarItemByUid(octxt, uid.toLowerCase()); if (item != null) { OfflineLog.offline.debug( "coercing Outlook calitem [%d] UID to upper case", item.getId()); boolean success = false; try { beginTransaction("forceUpperAppointment", octxt); uncache(item); DbOfflineMailbox.forceUidUpperCase(this, uid.toLowerCase()); item = super.getCalendarItemByUid(octxt, uid); assert (item != null); success = true; } finally { endTransaction(success); } } } else { // possible that we're receiving update from unpatched zcs which is in lower case and our // db is // already correct return the upper case equivalent; server will keep sending lower until // it's // patched but should handle pushes in upper since MySQL is case insensitive item = super.getCalendarItemByUid(octxt, uid.toUpperCase()); if (item != null) { OfflineLog.offline.debug("received lower case UID but our DB is already in upper case"); } } } return item; } finally { lock.release(); } }
void syncDate(OperationContext octxt, int itemId, MailItem.Type type, int date) throws ServiceException { if (date < 0) { return; } boolean success = false; try { beginTransaction("syncChangeIds", octxt); MailItem item = getItemById(itemId, type); markItemModified(item, Change.INTERNAL_ONLY); // update the database DbOfflineMailbox.setDate(item, date); // ... and update the in-memory item as well item.mData.date = date; success = true; } finally { endTransaction(success); } }
boolean renumberItem(OperationContext octxt, int id, MailItem.Type type, int newId) throws ServiceException { if (id == newId) { return true; } else if (id <= 0 || newId <= 0) { throw ServiceException.FAILURE( "invalid item id when renumbering (" + id + " => " + newId + ")", null); } lock.lock(); try { boolean success = false; try { beginTransaction("renumberItem", octxt); MailItem item = getItemById(id, type); if (item.getId() == newId) { OfflineLog.offline.info( "Item already renumbered; no need to renumber (%d => %d)", id, newId); return true; } else if (item.getId() != id) { OfflineLog.offline.warn( "renumbering item which may have already been renumbered (%d => %d) : itemId = %d", id, newId, item.getId()); } // changing a message's item id needs to purge its Conversation (virtual or real) if (item instanceof Message) uncacheItem(item.getParentId()); // mark old blob as disposable, but don't reindex item because INDEX_ID should still be // correct MailboxBlob mblob = item.getBlob(); if (mblob != null) { // register old blob for post-commit deletion item.markBlobForDeletion(); item.mBlob = null; // copy blob to new id (note that item.getSavedSequence() may change again later) try { MailboxBlob newBlob = StoreManager.getInstance().copy(mblob, this, newId, item.getSavedSequence()); markOtherItemDirty(newBlob); } catch (IOException e) { throw ServiceException.FAILURE( "could not link blob for renumbered item (" + id + " => " + newId + ")", e); } } // update the id in the database and in memory markItemDeleted(item.getType(), id); try { DbOfflineMailbox.renumberItem(item, newId); uncache(item); } catch (ServiceException se) { throw ServiceException.FAILURE( "Failure renumbering item name[" + item.getName() + "] subject[" + item.getSubject() + "]", se); } item.mId = item.mData.id = newId; item.markItemCreated(); if (item instanceof Folder || item instanceof Tag) { // replace with the new item cache(item); if (item instanceof Folder) { // sub folders might have wrong id List<Folder> subFolders = ((Folder) item).getSubfolders(octxt); for (Folder subFolder : subFolders) { subFolder.mData.folderId = newId; subFolder.mData.parentId = newId; cache(subFolder); // make sure it's in the cache } } // msgs are lazy-loaded so purge is safe purge(MailItem.Type.MESSAGE); } success = true; } catch (MailServiceException.NoSuchItemException nsie) { // item deleted from local before sync completes renumbering OfflineLog.offline.info( "item %d deleted from local db before sync completes renumbering to %d", id, newId); TypedIdList tombstones = new TypedIdList(); tombstones.add(type, newId, null); DbMailItem.writeTombstones(this, tombstones); success = true; return false; } finally { endTransaction(success); } mRenumbers.put(id, newId); return true; } finally { lock.release(); } }