Search in sources :

Example 21 with UnderlyingData

use of com.zimbra.cs.mailbox.MailItem.UnderlyingData in project zm-mailbox by Zimbra.

the class DbMailItem method getFoldersAndTags.

public static Mailbox.MailboxData getFoldersAndTags(Mailbox mbox, FolderTagMap folderData, FolderTagMap tagData, boolean forceReload) throws ServiceException {
    boolean reload = forceReload;
    DbConnection conn = mbox.getOperationConnection();
    PreparedStatement stmt = null;
    ResultSet rs = null;
    try {
        String table = getMailItemTableName(mbox, "mi");
        // folder data is loaded from the MAIL_ITEM table...
        stmt = conn.prepareStatement("SELECT " + DB_FIELDS + " FROM " + table + " WHERE " + IN_THIS_MAILBOX_AND + "type IN " + FOLDER_TYPES);
        setMailboxId(stmt, mbox, 1);
        rs = stmt.executeQuery();
        while (rs.next()) {
            UnderlyingData data = constructItem(rs);
            MailItem.Type type = MailItem.Type.of(data.type);
            if (MailItem.isAcceptableType(MailItem.Type.FOLDER, type)) {
                folderData.put(data, null);
            } else if (MailItem.isAcceptableType(MailItem.Type.TAG, type)) {
                tagData.put(data, null);
            }
            rs.getInt(CI_UNREAD);
            reload |= rs.wasNull();
        }
        rs.close();
        // tag data is loaded from a different table...
        reload |= DbTag.getAllTags(mbox, tagData);
        for (UnderlyingData data : folderData.keySet()) {
            if (data.parentId != data.folderId) {
                // we had a small folder data inconsistency issue, so resolve it here
                // rather than returning it up to the caller
                stmt.close();
                stmt = conn.prepareStatement("UPDATE " + table + " SET parent_id = folder_id" + " WHERE " + IN_THIS_MAILBOX_AND + "id = ?");
                int pos = 1;
                pos = setMailboxId(stmt, mbox, pos);
                stmt.setInt(pos++, data.id);
                stmt.executeUpdate();
                data.parentId = data.folderId;
                ZimbraLog.mailbox.info("correcting PARENT_ID column for %s %d", MailItem.Type.of(data.type), data.id);
            }
        }
        if (!reload) {
            return null;
        }
        Map<Integer, UnderlyingData> lookup = new HashMap<Integer, UnderlyingData>(folderData.size() + tagData.size());
        // going to recalculate counts, so discard any existing counts...
        for (FolderTagMap itemData : new FolderTagMap[] { folderData, tagData }) {
            for (Map.Entry<UnderlyingData, FolderTagCounts> entry : itemData.entrySet()) {
                UnderlyingData data = entry.getKey();
                lookup.put(data.id, data);
                data.size = data.unreadCount = 0;
                entry.setValue(new FolderTagCounts());
            }
        }
        rs.close();
        stmt.close();
        // recalculate the counts for all folders and the overall mailbox size...
        Mailbox.MailboxData mbd = new Mailbox.MailboxData();
        stmt = conn.prepareStatement("SELECT folder_id, type, flags, COUNT(*), SUM(unread), SUM(size)" + " FROM " + table + " WHERE " + IN_THIS_MAILBOX_AND + "type NOT IN " + NON_SEARCHABLE_TYPES + " GROUP BY folder_id, type, flags");
        setMailboxId(stmt, mbox, 1);
        rs = stmt.executeQuery();
        while (rs.next()) {
            int folderId = rs.getInt(1);
            byte type = rs.getByte(2);
            boolean deleted = (rs.getInt(3) & Flag.BITMASK_DELETED) != 0;
            int count = rs.getInt(4);
            int unread = rs.getInt(5);
            long size = rs.getLong(6);
            if (type == MailItem.Type.CONTACT.toByte()) {
                mbd.contacts += count;
            }
            mbd.size += size;
            UnderlyingData data = lookup.get(folderId);
            if (data != null) {
                data.unreadCount += unread;
                data.size += count;
                FolderTagCounts fcounts = folderData.get(data);
                fcounts.totalSize += size;
                if (deleted) {
                    fcounts.deletedCount += count;
                    fcounts.deletedUnreadCount += unread;
                }
            } else {
                ZimbraLog.mailbox.warn("inconsistent DB state: items with no corresponding folder (folder id %d)", folderId);
            }
        }
        // recalculate the counts for all tags...
        DbTag.recalculateTagCounts(mbox, lookup);
        rs.close();
        stmt.close();
        stmt = conn.prepareStatement("SELECT mi.folder_id, SUM(rev.size)" + " FROM " + table + ", " + getRevisionTableName(mbox, "rev") + " WHERE mi.id = rev.item_id" + (DebugConfig.disableMailboxGroups ? "" : " AND rev.mailbox_id = ? AND mi.mailbox_id = rev.mailbox_id") + " GROUP BY folder_id");
        setMailboxId(stmt, mbox, 1);
        rs = stmt.executeQuery();
        while (rs.next()) {
            int folderId = rs.getInt(1);
            long size = rs.getLong(2);
            mbd.size += size;
            UnderlyingData data = lookup.get(folderId);
            if (data != null) {
                folderData.get(data).totalSize += size;
            } else {
                ZimbraLog.mailbox.warn("inconsistent DB state: revisions with no corresponding folder (folder ID " + folderId + ")");
            }
        }
        return mbd;
    } catch (SQLException e) {
        throw ServiceException.FAILURE("fetching folder data for mailbox " + mbox.getId(), e);
    } finally {
        DbPool.closeResults(rs);
        DbPool.closeStatement(stmt);
    }
}
Also used : HashMap(java.util.HashMap) SQLException(java.sql.SQLException) UnderlyingData(com.zimbra.cs.mailbox.MailItem.UnderlyingData) PreparedStatement(java.sql.PreparedStatement) DbConnection(com.zimbra.cs.db.DbPool.DbConnection) MailItem(com.zimbra.cs.mailbox.MailItem) Mailbox(com.zimbra.cs.mailbox.Mailbox) ResultSet(java.sql.ResultSet) Map(java.util.Map) EnumMap(java.util.EnumMap) HashMap(java.util.HashMap)

Example 22 with UnderlyingData

use of com.zimbra.cs.mailbox.MailItem.UnderlyingData in project zm-mailbox by Zimbra.

the class DbMailItem method constructItem.

static UnderlyingData constructItem(ResultSet rs, int offset, boolean fromDumpster) throws SQLException, ServiceException {
    UnderlyingData data = new UnderlyingData();
    data.id = rs.getInt(CI_ID + offset);
    data.type = rs.getByte(CI_TYPE + offset);
    data.parentId = rs.getInt(CI_PARENT_ID + offset);
    data.folderId = rs.getInt(CI_FOLDER_ID + offset);
    data.setPrevFolders(rs.getString(CI_PREV_FOLDERS + offset));
    data.indexId = rs.getInt(CI_INDEX_ID + offset);
    if (rs.wasNull()) {
        data.indexId = MailItem.IndexStatus.NO.id();
    }
    data.imapId = rs.getInt(CI_IMAP_ID + offset);
    if (rs.wasNull()) {
        data.imapId = -1;
    }
    data.date = rs.getInt(CI_DATE + offset);
    data.size = rs.getLong(CI_SIZE + offset);
    data.locator = rs.getString(CI_LOCATOR + offset);
    data.setBlobDigest(rs.getString(CI_BLOB_DIGEST + offset));
    data.unreadCount = rs.getInt(CI_UNREAD + offset);
    int flags = rs.getInt(CI_FLAGS + offset);
    if (!fromDumpster) {
        data.setFlags(flags);
    } else {
        data.setFlags(flags | Flag.BITMASK_UNCACHED | Flag.BITMASK_IN_DUMPSTER);
    }
    data.setTags(new Tag.NormalizedTags(DbTag.deserializeTags(rs.getString(CI_TAGS + offset))));
    data.setSubject(rs.getString(CI_SUBJECT + offset));
    data.name = rs.getString(CI_NAME + offset);
    data.metadata = decodeMetadata(rs.getString(CI_METADATA + offset));
    data.modMetadata = rs.getInt(CI_MODIFIED + offset);
    data.modContent = rs.getInt(CI_SAVED + offset);
    data.dateChanged = rs.getInt(CI_MODIFY_DATE + offset);
    // make sure to handle NULL column values
    if (data.parentId == 0) {
        data.parentId = -1;
    }
    if (data.dateChanged == 0) {
        data.dateChanged = -1;
    }
    data.uuid = rs.getString(CI_UUID + offset);
    return data;
}
Also used : UnderlyingData(com.zimbra.cs.mailbox.MailItem.UnderlyingData) Tag(com.zimbra.cs.mailbox.Tag)

Example 23 with UnderlyingData

use of com.zimbra.cs.mailbox.MailItem.UnderlyingData in project zm-mailbox by Zimbra.

the class DbMailItem method constructRevision.

private static UnderlyingData constructRevision(ResultSet rs, MailItem item, boolean fromDumpster) throws SQLException, ServiceException {
    UnderlyingData data = new UnderlyingData();
    data.id = item.getId();
    data.type = item.getType().toByte();
    data.parentId = item.getParentId();
    data.folderId = item.getFolderId();
    data.indexId = MailItem.IndexStatus.NO.id();
    data.imapId = -1;
    data.date = rs.getInt(1);
    data.size = rs.getLong(2);
    data.locator = rs.getString(3);
    data.setBlobDigest(rs.getString(4));
    data.unreadCount = item.getUnreadCount();
    if (!fromDumpster) {
        data.setFlags(item.getInternalFlagBitmask() | Flag.BITMASK_UNCACHED);
    } else {
        data.setFlags(item.getInternalFlagBitmask() | Flag.BITMASK_UNCACHED | Flag.BITMASK_IN_DUMPSTER);
    }
    data.setTags(new Tag.NormalizedTags(item.getTags()));
    data.setSubject(item.getSubject());
    data.name = rs.getString(5);
    data.metadata = decodeMetadata(rs.getString(6));
    data.modMetadata = rs.getInt(7);
    data.dateChanged = rs.getInt(8);
    data.modContent = rs.getInt(9);
    // make sure to handle NULL column values
    if (data.parentId <= 0) {
        data.parentId = -1;
    }
    if (data.dateChanged == 0) {
        data.dateChanged = -1;
    }
    data.uuid = item.getUuid();
    return data;
}
Also used : UnderlyingData(com.zimbra.cs.mailbox.MailItem.UnderlyingData) Tag(com.zimbra.cs.mailbox.Tag)

Example 24 with UnderlyingData

use of com.zimbra.cs.mailbox.MailItem.UnderlyingData in project zm-mailbox by Zimbra.

the class DbMailItem method getByFolder.

public static List<UnderlyingData> getByFolder(Folder folder, MailItem.Type type, SortBy sort) throws ServiceException {
    if (Mailbox.isCachedType(type)) {
        throw ServiceException.INVALID_REQUEST("folders and tags must be retrieved from cache", null);
    }
    Mailbox mbox = folder.getMailbox();
    List<UnderlyingData> result = new ArrayList<UnderlyingData>();
    DbConnection conn = mbox.getOperationConnection();
    PreparedStatement stmt = null;
    ResultSet rs = null;
    try {
        stmt = conn.prepareStatement("SELECT " + DB_FIELDS + " FROM " + getMailItemTableName(folder.getMailbox(), " mi") + " WHERE " + IN_THIS_MAILBOX_AND + "folder_id = ? AND " + typeIn(type) + DbSearch.orderBy(sort, false));
        if (folder.getSize() > RESULTS_STREAMING_MIN_ROWS && type == MailItem.Type.MESSAGE) {
            Db.getInstance().enableStreaming(stmt);
        }
        int pos = 1;
        pos = setMailboxId(stmt, mbox, pos);
        stmt.setInt(pos++, folder.getId());
        rs = stmt.executeQuery();
        while (rs.next()) {
            result.add(constructItem(rs));
        }
        return result;
    } catch (SQLException e) {
        throw ServiceException.FAILURE("fetching items in folder " + folder.getId(), e);
    } finally {
        DbPool.closeResults(rs);
        DbPool.closeStatement(stmt);
    }
}
Also used : Mailbox(com.zimbra.cs.mailbox.Mailbox) SQLException(java.sql.SQLException) UnderlyingData(com.zimbra.cs.mailbox.MailItem.UnderlyingData) ArrayList(java.util.ArrayList) ResultSet(java.sql.ResultSet) PreparedStatement(java.sql.PreparedStatement) DbConnection(com.zimbra.cs.db.DbPool.DbConnection)

Example 25 with UnderlyingData

use of com.zimbra.cs.mailbox.MailItem.UnderlyingData in project zm-mailbox by Zimbra.

the class DbMailItem method consistencyCheck.

public static void consistencyCheck(MailItem item, UnderlyingData data, String metadata) throws ServiceException {
    if (item.getId() <= 0) {
        return;
    }
    Mailbox mbox = item.getMailbox();
    DbConnection conn = mbox.getOperationConnection();
    PreparedStatement stmt = null;
    ResultSet rs = null;
    try {
        stmt = conn.prepareStatement("SELECT mi.sender, " + DB_FIELDS + " FROM " + getMailItemTableName(mbox, "mi") + " WHERE " + IN_THIS_MAILBOX_AND + "id = ?");
        int pos = 1;
        pos = setMailboxId(stmt, mbox, pos);
        stmt.setInt(pos++, item.getId());
        rs = stmt.executeQuery();
        if (!rs.next()) {
            throw ServiceException.FAILURE("consistency check failed: " + item.getType() + " " + item.getId() + " not found in DB", null);
        }
        UnderlyingData dbdata = constructItem(rs, 1);
        String dbsender = rs.getString(1);
        String dataBlobDigest = data.getBlobDigest(), dbdataBlobDigest = dbdata.getBlobDigest();
        String dataSender = item.getSortSender(), dbdataSender = dbsender == null ? "" : dbsender;
        String failures = "";
        if (data.id != dbdata.id) {
            failures += " ID";
        }
        if (data.type != dbdata.type) {
            failures += " TYPE";
        }
        if (data.folderId != dbdata.folderId) {
            failures += " FOLDER_ID";
        }
        if (StringUtil.equal(data.getPrevFolders(), dbdata.getPrevFolders())) {
            failures += " PREV_FOLDERS";
        }
        if (data.indexId != dbdata.indexId) {
            failures += " INDEX_ID";
        }
        if (data.imapId != dbdata.imapId) {
            failures += " IMAP_ID";
        }
        if (!StringUtil.equal(data.locator, dbdata.locator)) {
            failures += " LOCATOR";
        }
        if (data.date != dbdata.date) {
            failures += " DATE";
        }
        if (data.size != dbdata.size) {
            failures += " SIZE";
        }
        if (dbdata.type != MailItem.Type.CONVERSATION.toByte()) {
            if (data.unreadCount != dbdata.unreadCount) {
                failures += " UNREAD";
            }
            if (data.getFlags() != dbdata.getFlags()) {
                failures += " FLAGS";
            }
            if (!TagUtil.tagsMatch(data.getTags(), dbdata.getTags())) {
                failures += " TAGS";
            }
        }
        if (data.modMetadata != dbdata.modMetadata) {
            failures += " MOD_METADATA";
        }
        if (data.dateChanged != dbdata.dateChanged) {
            failures += " CHANGE_DATE";
        }
        if (data.modContent != dbdata.modContent) {
            failures += " MOD_CONTENT";
        }
        if (Math.max(data.parentId, -1) != dbdata.parentId) {
            failures += " PARENT_ID";
        }
        if (dataBlobDigest != dbdataBlobDigest && (dataBlobDigest == null || !dataBlobDigest.equals(dbdataBlobDigest))) {
            failures += " BLOB_DIGEST";
        }
        if (dataSender != dbdataSender && (dataSender == null || !dataSender.equalsIgnoreCase(dbdataSender))) {
            failures += " SENDER";
        }
        if (data.getSubject() != dbdata.getSubject() && (data.getSubject() == null || !data.getSubject().equals(dbdata.getSubject()))) {
            failures += " SUBJECT";
        }
        if (data.name != dbdata.name && (data.name == null || !data.name.equals(dbdata.name))) {
            failures += " NAME";
        }
        if (metadata != dbdata.metadata && (metadata == null || !metadata.equals(dbdata.metadata))) {
            failures += " METADATA";
        }
        if (item instanceof Folder && dbdata.folderId != dbdata.parentId) {
            failures += " FOLDER!=PARENT";
        }
        if (!failures.equals("")) {
            throw ServiceException.FAILURE("consistency check failed: " + item.getType() + " " + item.getId() + " differs from DB at" + failures, null);
        }
    } catch (SQLException e) {
        throw ServiceException.FAILURE("fetching item " + item.getId(), e);
    } finally {
        DbPool.closeResults(rs);
        DbPool.closeStatement(stmt);
    }
}
Also used : Mailbox(com.zimbra.cs.mailbox.Mailbox) SQLException(java.sql.SQLException) UnderlyingData(com.zimbra.cs.mailbox.MailItem.UnderlyingData) ResultSet(java.sql.ResultSet) PreparedStatement(java.sql.PreparedStatement) Folder(com.zimbra.cs.mailbox.Folder) DbConnection(com.zimbra.cs.db.DbPool.DbConnection)

Aggregations

UnderlyingData (com.zimbra.cs.mailbox.MailItem.UnderlyingData)30 PreparedStatement (java.sql.PreparedStatement)21 SQLException (java.sql.SQLException)21 ResultSet (java.sql.ResultSet)20 DbConnection (com.zimbra.cs.db.DbPool.DbConnection)18 ArrayList (java.util.ArrayList)13 Mailbox (com.zimbra.cs.mailbox.Mailbox)8 Tag (com.zimbra.cs.mailbox.Tag)4 ServiceException (com.zimbra.common.service.ServiceException)3 MailItem (com.zimbra.cs.mailbox.MailItem)3 IOException (java.io.IOException)3 HashMap (java.util.HashMap)3 Color (com.zimbra.common.mailbox.Color)2 BufferStream (com.zimbra.common.util.BufferStream)2 ZMimeMessage (com.zimbra.common.zmime.ZMimeMessage)2 ZSharedFileInputStream (com.zimbra.common.zmime.ZSharedFileInputStream)2 DbMailItem (com.zimbra.cs.db.DbMailItem)2 Folder (com.zimbra.cs.mailbox.Folder)2 ArchiveInputEntry (com.zimbra.cs.service.formatter.ArchiveFormatter.ArchiveInputEntry)2 ArchiveInputStream (com.zimbra.cs.service.formatter.ArchiveFormatter.ArchiveInputStream)2