// --fldmtrc.cpp----------------------------------------------------------------
//
// Implements the folder metrics code.
//
// Copyright (C) Microsoft Corp. 1986-1996. All Rights Reserved.
// -----------------------------------------------------------------------------
#include "edk.h"
#include "fldmtrc.h"
#include "fldmtrc.chk"
// Class constants
// ---------------
SPropTagArray CFolderMetrics::m_sFolderContentCount = { 1L, {PR_CONTENT_COUNT } };
SSortOrderSet CFolderMetrics::m_sSortOrderSet = { 1L, 0, 0, {PR_MESSAGE_DELIVERY_TIME , TABLE_SORT_ASCEND} };
SPropTagArray CFolderMetrics::m_sInFolderSince = { 1L, {PR_MESSAGE_DELIVERY_TIME } };
//$--CFolderMetrics::CFolderMetrics---------------------------------------------
// Constructor for Folder Metrics object.
// -----------------------------------------------------------------------------
CFolderMetrics::CFolderMetrics()
{
DEBUGPUBLIC("CFolderMetrics::CFolderMetrics()\n");
m_lpFolder = NULL;
m_lpTable = NULL;
}
//$--CFolderMetrics::~CFolderMetrics--------------------------------------------
// Destructor for folder Metrics object.
// -----------------------------------------------------------------------------
CFolderMetrics::~CFolderMetrics()
{
DEBUGPUBLIC("CFolderMetrics::~CFolderMetrics()\n");
// m_lpFolder isn't freed because we didn't create it.
// ---------------------------------------------------
ULRELEASE(m_lpTable);
}
//$--CFolderMetrics::HrReset----------------------------------------------------
// Resets and assigns the folder metrics object to a particular folder.
// -----------------------------------------------------------------------------
HRESULT CFolderMetrics::HrReset( // HRESULT
IN LPMAPIFOLDER lpFolder) // Object is assigned to this folder.
{
HRESULT hr = NOERROR;
DEBUGPRIVATE("CFolderMetrics::HrReset()\n");
hr = CHK_CFolderMetrics_HrReset(lpFolder);
if (FAILED(hr))
RETURN(hr);
if (lpFolder == NULL)
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
ULRELEASE(m_lpTable);
// Open content table for lpFolder and set columns for PR_IN_FOLDER_SINCE
// ----------------------------------------------------------------------
hr = lpFolder->GetContentsTable(MAPI_DEFERRED_ERRORS, &m_lpTable);
if (FAILED(hr))
{
goto cleanup;
}
hr = m_lpTable->SetColumns(&m_sInFolderSince, (ULONG)0);
if (FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
m_lpFolder = lpFolder;
cleanup:
// m_lpFolder isn't freed because we didn't create it.
// ---------------------------------------------------
RETURN(hr);
}
//$--CFolderMetrics::HrGetFolderMetrics-----------------------------------------
// Determine and return the folder metrics values.
// -----------------------------------------------------------------------------
HRESULT CFolderMetrics::HrGetFolderMetrics( // RETURNS: HRESULT
IN __int64 liNow, // Current time expressed as a file time.
IN DWORD fMetric, // Flag to determine the metric
// to query. May be an or'ed
// combination of:
// FM_CMESSAGES, FM_LONGEST_WAIT
// FM_TOTAL_WAIT.
OUT DWORD &cMessages, // Receives number of mesages
// in folder if FM_CMESSAGES
// is specified. = 0 otherwise.
OUT __int64 &liLongestWait, // Receives longest wait
// expressed as a file time if
// FM_LONGEST_WAIT specified.
// = 0 otherwise.
OUT __int64 &liTotalWait) // Recieves total wait
// expresses as a file time if
// FM_TOTAL_WAIT specified.
// = 0 otherwise.
{
HRESULT hr = NOERROR;
DEBUGPRIVATE("CFolderMetrics::HrGetFolderMetrics()\n");
// pre-clear all return values
// ---------------------------
cMessages = 0;
liLongestWait = 0;
liTotalWait = 0;
hr = CHK_CFolderMetrics_HrGetFolderMetrics(
liNow,
fMetric,
cMessages,
liLongestWait,
liTotalWait);
if (FAILED(hr))
RETURN(hr);
// The message count can be generated as a side effect of
// calculating the FM_TOTAL_WAIT or queried separately as a folder
// property. If FM_TOTAL_WAIT is not requested then
// then query the message count as a less expensive folder property.
// ----------------------------------------------------------
if (!(fMetric & FM_TOTAL_WAIT))
{
hr = HrGetcMessages(cMessages);
if (FAILED(hr))
{
goto cleanup;
}
}
// Re-sort contents table and go to the start of the table.
// --------------------------------------------------------
hr = m_lpTable->SortTable(&m_sSortOrderSet, 0);
if (FAILED(hr))
{
goto cleanup;
}
hr = m_lpTable->SeekRow(BOOKMARK_BEGINNING, 0, NULL);
if (FAILED(hr))
{
goto cleanup;
}
// If longest wait metric requested, then get longest wait.
// --------------------------------------------------------
if (fMetric & FM_LONGEST_WAIT)
{
hr = HrGetLongestWait(liNow, liLongestWait);
if (FAILED(hr))
{
goto cleanup;
}
}
// If total wait metric requested, then get total wait.
// ----------------------------------------------------
if (fMetric & FM_TOTAL_WAIT)
{
hr = HrGetTotalWait(liNow, cMessages, liTotalWait);
if (FAILED(hr))
{
goto cleanup;
}
}
cleanup:
// if they didn't ask for it then don't give it to them.
// -----------------------------------------------------
if (!(fMetric & FM_CMESSAGES))
{
cMessages = 0;
}
if (!(fMetric & FM_LONGEST_WAIT))
{
liLongestWait = 0;
}
if (!(fMetric & FM_TOTAL_WAIT))
{
liTotalWait = 0;
}
RETURN(hr);
}
// -----------------------------------------------------------------------------
// Private member functions
// -----------------------------------------------------------------------------
//$--CFolderMetrics::HrGetcMessages---------------------------------------------
// Returns the number of messages in the object folder.
// -----------------------------------------------------------------------------
HRESULT CFolderMetrics::HrGetcMessages( // RETURNS: HRESULT
OUT DWORD &cMessage) // Receives number of messages in folder.
{
HRESULT hr = NOERROR;
DWORD cValues = 0;
LPSPropValue lpPropValue = NULL;
DEBUGPRIVATE("CFolderMetrics::HrGetMessages()\n");
hr = CHK_CFolderMetrics_HrGetcMessages(cMessage);
if (FAILED(hr))
RETURN(hr);
cMessage = 0;
hr = m_lpFolder->GetProps(
&m_sFolderContentCount, fMapiUnicode, &cValues, &lpPropValue);
if (FAILED(hr) || (hr == MAPI_W_ERRORS_RETURNED))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
if ( cValues > 0 )
{
cMessage = (DWORD) lpPropValue->Value.l;
}
cleanup:
MAPIFREEBUFFER(lpPropValue);
RETURN(hr);
}
//$--CFolderMetrics::HrGetLongestWait-------------------------------------------
// Retrieves duration in the folder of the oldest message.
// -----------------------------------------------------------------------------
HRESULT CFolderMetrics::HrGetLongestWait( // RETURNS: HRESULT
IN __int64 liNow, // Current Time expressed as a
// file time.
OUT __int64 &liLongestWait) // Receives the longest time that
// a messages has been in
// the folder expressed as a
// file time.
{
HRESULT hr = NOERROR;
LONG lRes = 0;
LPSRowSet lpRows = NULL;
LPSPropValue lpProps = NULL;
ULONG ulType = 0;
__int64 liInFolderSince= 0;
DEBUGPRIVATE("CFolderMetrics::HrGetLongestWait()\n");
hr = CHK_CFolderMetrics_HrGetLongestWait(liNow, liLongestWait);
if (FAILED(hr))
RETURN(hr);
liLongestWait = 0;
hr = m_lpTable->QueryRows(1, TBL_NOADVANCE, &lpRows);
if (FAILED(hr) || (hr == MAPI_W_ERRORS_RETURNED))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// If no entries, then quit.
// -------------------------
if (lpRows->cRows == 0)
{
goto cleanup;
}
// If number values differs from 1 then quit.
// ------------------------------------------
if (lpRows->aRow[0].cValues != 1)
{
ASSERTERROR(FALSE,"CFolderMetrics::rcGetLongestWait() Content "
"table contains other than 1 Value type.");
goto cleanup;
}
lpProps = lpRows->aRow[0].lpProps;
ulType = PROP_TYPE(lpProps->ulPropTag);
if (ulType!= PT_SYSTIME)
{
// OK, fake it
liLongestWait = 0 ;
goto cleanup ;
}
// If time is more recent than now then ignore it.
// -----------------------------------------------
liInFolderSince = INT64_FROM_FILETIME(lpProps->Value.ft);
if (liInFolderSince < liNow)
{
liLongestWait = liNow - liInFolderSince;
}
cleanup:
FreeProws(lpRows);
RETURN(hr);
}
//$--HrGetTotalWait-------------------------------------------------------------
// Returns the sum of all of the waiting periods of each message in the folder.
// -----------------------------------------------------------------------------
HRESULT CFolderMetrics::HrGetTotalWait( // RETURNS: HRESULT
IN __int64 liNow, // Current time expressed as a file time.
OUT DWORD &cMessages, // Receives number of messages in file.
OUT __int64 &liTotalWait) // Receives total wait of messages in file.
{
HRESULT hr = NOERROR;
LONG lRes = 0;
__int64 liInFolderSince = 0;
LPSRowSet lpRows = NULL;
LPSPropValue lpProps = NULL;
DWORD i = 0;
DWORD cRows = 0;
DEBUGPRIVATE("CFolderMetrics::HrGetTotalWait()\n");
hr = CHK_CFolderMetrics_HrGetTotalWait(liNow, cMessages, liTotalWait);
if (FAILED(hr))
RETURN(hr);
liInFolderSince = 0;
liTotalWait = 0;
cMessages = 0;
// Read entries 100 at a time and calculate the total wait
// from the in folder since time.
// ---------------------------------------------------------
do
{
hr = m_lpTable->QueryRows(100, 0, &lpRows);
if (FAILED(hr) || (hr == MAPI_W_ERRORS_RETURNED))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
cMessages += lpRows->cRows;
cRows = lpRows->cRows;
for (i=0; i<cRows; i++)
{
// Get the property value from the row.
// ------------------------------------
if (lpRows->aRow[i].cValues != 1)
{
ASSERTERROR(FALSE,"Content table contains other than 1 "
"Value type.");
goto cleanup;
}
lpProps = lpRows->aRow[i].lpProps;
if (PROP_TYPE(lpProps->ulPropTag) != PT_SYSTIME)
{
// ok, fake it.
continue ;
}
// If folder submit time is more recent than
// now, then don't include this item in average.
// ----------------------------------------------
liInFolderSince = INT64_FROM_FILETIME(lpProps->Value.ft);
if (liInFolderSince < liNow)
{
liTotalWait = liTotalWait + (liNow - liInFolderSince);
}
}
FreeProws(lpRows);
lpRows = NULL;
}
while (cRows != 0); // end of DO { } WHILE () .
cleanup:
FreeProws(lpRows);
RETURN(hr);
}