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);
}
}
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;
}
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;
}
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);
}
}
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);
}
}
Aggregations