Ejemplo n.º 1
0
/**
 * Checks in the ECStatsTable PR_EC_STATSTABLE_USERS for quota
 * information per connected server given in lpAdminStore.
 *
 * @param[in]	cUsers		number of users in lpsUserList
 * @param[in]	lpsUserList	array of ECUser struct, containing all Zarafa from all companies, on any server
 * @param[in]	lpecCompany	same company struct as in ECQuotaMonitor::CheckCompanyQuota()
 * @param[in]	lpAdminStore IMsgStore of SYSTEM user on a specific server instance.
 * @return hrSuccess or any MAPI error code.
 */
HRESULT ECQuotaMonitor::CheckServerQuota(ULONG cUsers, LPECUSER lpsUserList, LPECCOMPANY lpecCompany, LPMDB lpAdminStore)
{
	HRESULT hr = hrSuccess;
	LPSRestriction lpsRestriction = NULL;
	SPropValue sRestrictProp;
	LPMAPITABLE lpTable = NULL;
	LPSRowSet lpRowSet = NULL;
	ECQUOTASTATUS sQuotaStatus;
	ULONG i, u;
	SizedSPropTagArray(5, sCols) = {
		5, {
			PR_EC_USERNAME_A,
			PR_MESSAGE_SIZE_EXTENDED,
			PR_QUOTA_WARNING_THRESHOLD,
			PR_QUOTA_SEND_THRESHOLD,
			PR_QUOTA_RECEIVE_THRESHOLD,
		}
	};

	hr = lpAdminStore->OpenProperty(PR_EC_STATSTABLE_USERS, &IID_IMAPITable, 0, 0, (LPUNKNOWN*)&lpTable);
	if (hr != hrSuccess) {
		m_lpThreadMonitor->lpLogger->Log(EC_LOGLEVEL_FATAL, "Unable to open stats table for quota sizes, error 0x%08X", hr);
		goto exit;
	}

	hr = lpTable->SetColumns((LPSPropTagArray)&sCols, MAPI_DEFERRED_ERRORS);
	if (hr != hrSuccess) {
		m_lpThreadMonitor->lpLogger->Log(EC_LOGLEVEL_FATAL, "Unable to set columns on stats table for quota sizes, error 0x%08X", hr);
		goto exit;
	}

	if (lpecCompany->sCompanyId.cb != 0 && lpecCompany->sCompanyId.lpb != NULL) {
		sRestrictProp.ulPropTag = PR_EC_COMPANY_NAME_A;
		sRestrictProp.Value.lpszA = (char*)lpecCompany->lpszCompanyname;

		CREATE_RESTRICTION(lpsRestriction);
		CREATE_RES_OR(lpsRestriction, lpsRestriction, 2);
		  CREATE_RES_NOT(lpsRestriction, &lpsRestriction->res.resOr.lpRes[0]);
		    DATA_RES_EXIST(lpsRestriction, lpsRestriction->res.resOr.lpRes[0].res.resNot.lpRes[0], PR_EC_COMPANY_NAME_A);
		  DATA_RES_PROPERTY(lpsRestriction, lpsRestriction->res.resOr.lpRes[1], RELOP_EQ, PR_EC_COMPANY_NAME_A, &sRestrictProp);

		hr = lpTable->Restrict(lpsRestriction, MAPI_DEFERRED_ERRORS);
		if (hr != hrSuccess) {
			m_lpThreadMonitor->lpLogger->Log(EC_LOGLEVEL_FATAL, "Unable to restrict stats table, error 0x%08X", hr);
			goto exit;
		}
	}

	while (TRUE) {
		hr = lpTable->QueryRows(50, 0, &lpRowSet);
		if (hr != hrSuccess) {
			m_lpThreadMonitor->lpLogger->Log(EC_LOGLEVEL_FATAL, "Unable to receive stats table data, error 0x%08X", hr);
			goto exit;
		}

		if (lpRowSet->cRows == 0)
			break;

		for (i = 0; i < lpRowSet->cRows; i++) {
			LPSPropValue lpUsername = NULL;
			LPSPropValue lpStoreSize = NULL;
			LPSPropValue lpQuotaWarn = NULL;
			LPSPropValue lpQuotaSoft = NULL;
			LPSPropValue lpQuotaHard = NULL;
			MsgStorePtr ptrStore;

			lpUsername = PpropFindProp(lpRowSet->aRow[i].lpProps, lpRowSet->aRow[i].cValues, PR_EC_USERNAME_A);
			lpStoreSize = PpropFindProp(lpRowSet->aRow[i].lpProps, lpRowSet->aRow[i].cValues, PR_MESSAGE_SIZE_EXTENDED);
			lpQuotaWarn = PpropFindProp(lpRowSet->aRow[i].lpProps, lpRowSet->aRow[i].cValues, PR_QUOTA_WARNING_THRESHOLD);
			lpQuotaSoft = PpropFindProp(lpRowSet->aRow[i].lpProps, lpRowSet->aRow[i].cValues, PR_QUOTA_SEND_THRESHOLD);
			lpQuotaHard = PpropFindProp(lpRowSet->aRow[i].lpProps, lpRowSet->aRow[i].cValues, PR_QUOTA_RECEIVE_THRESHOLD);

			if (!lpUsername || !lpStoreSize)
				continue;		// don't log error: could be for several valid reasons (contacts, other server, etc)

			if (lpStoreSize->Value.li.QuadPart == 0)
				continue;

			m_ulProcessed++;

			memset(&sQuotaStatus, 0, sizeof(ECQUOTASTATUS));

			sQuotaStatus.llStoreSize = lpStoreSize->Value.li.QuadPart;
			sQuotaStatus.quotaStatus = QUOTA_OK;
			if (lpQuotaHard && lpQuotaHard->Value.ul > 0 && lpStoreSize->Value.li.QuadPart > ((long long)lpQuotaHard->Value.ul * 1024))
				sQuotaStatus.quotaStatus = QUOTA_HARDLIMIT;
			else if (lpQuotaSoft && lpQuotaSoft->Value.ul > 0 && lpStoreSize->Value.li.QuadPart > ((long long)lpQuotaSoft->Value.ul * 1024))
				sQuotaStatus.quotaStatus = QUOTA_SOFTLIMIT;
			else if (lpQuotaWarn && lpQuotaWarn->Value.ul > 0 && lpStoreSize->Value.li.QuadPart > ((long long)lpQuotaWarn->Value.ul * 1024))
				sQuotaStatus.quotaStatus = QUOTA_WARN;

			if (sQuotaStatus.quotaStatus == QUOTA_OK)
				continue;

			m_lpThreadMonitor->lpLogger->Log(EC_LOGLEVEL_FATAL, "Mailbox of user %s has exceeded its %s limit", lpUsername->Value.lpszA, sQuotaStatus.quotaStatus == QUOTA_WARN ? "warning" : sQuotaStatus.quotaStatus == QUOTA_SOFTLIMIT ? "soft" : "hard");

			// find the user in the full users list
			for (u = 0; u < cUsers; u++) {
				if (strcmp((char*)lpsUserList[u].lpszUsername, lpUsername->Value.lpszA) == 0)
					break;
			}
			if (u == cUsers) {
				m_lpThreadMonitor->lpLogger->Log(EC_LOGLEVEL_ERROR, "Unable to find user %s in userlist", lpUsername->Value.lpszA);
				m_ulFailed++;
				continue;
			}
			hr = OpenUserStore(lpsUserList[u].lpszUsername, &ptrStore);
			if (hr != hrSuccess) {
				hr = hrSuccess;
				continue;
			}
			hr = Notify(&lpsUserList[u], lpecCompany, &sQuotaStatus, ptrStore);
			if (hr != hrSuccess)
				m_ulFailed++;
		}

		if (lpRowSet)
			FreeProws(lpRowSet);
		lpRowSet = NULL;
	}

exit:
	if (lpRowSet)
		FreeProws(lpRowSet);

	if (lpsRestriction)
		MAPIFreeBuffer(lpsRestriction);

	if (lpTable)
		lpTable->Release();

	return hr;
}