Esempio n. 1
0
IMAPIAdviseSink * MAPIStorageAdviser::_GetSink( CMAPIAdviseSink * pMapiNotifySink )
{
  ASSERT(pMapiNotifySink);

  IMAPIAdviseSink * pMapiSink = NULL;
  HRESULT hr = pMapiNotifySink->QueryInterface(IID_IMAPIAdviseSink, (void **)&pMapiSink);
  if(FAILED(hr)){
    pMapiSink->Release();
    return NULL;
  }

  return pMapiSink;
}
Esempio n. 2
0
/**
 * Opens an admin session and the outgoing queue. If either one
 * produces an error this function will return. If the queue is empty,
 * it will wait for a notification when new data is present in the
 * outgoing queue table.
 *
 * @param[in]	szSMTP	The SMTP server to send to.
 * @param[in]	ulPort	The SMTP port to sent to.
 * @param[in]	szPath	URI of Zarafa server to connect to, must be file:// or https:// with valid ssl certificates.
 * @return		HRESULT
 */
HRESULT ProcessQueue(char* szSMTP, int ulPort, char *szPath)
{
	HRESULT				hr				= hrSuccess;
	IMAPISession		*lpAdminSession = NULL;
	IECSpooler			*lpSpooler		= NULL;
	IMAPITable			*lpTable		= NULL;
	IMAPIAdviseSink		*lpAdviseSink	= NULL;
	ULONG				ulConnection	= 0;

	SizedSPropTagArray(5, sOutgoingCols) = {
		5, {
			PR_EC_MAILBOX_OWNER_ACCOUNT_W,
			PR_STORE_ENTRYID,
			PR_ENTRYID,
			PR_EC_OUTGOING_FLAGS,
			PR_DEFERRED_SEND_TIME,
		}
	};
	
	SSortOrderSet sSort = { 1, 0, 0, { { PR_EC_HIERARCHYID, TABLE_SORT_ASCEND } } };

	hr = HrOpenECAdminSession(g_lpLogger, &lpAdminSession, "zarafa-spooler:system", PROJECT_SVN_REV_STR, szPath, EC_PROFILE_FLAGS_NO_PUBLIC_STORE,
							  g_lpConfig->GetSetting("sslkey_file", "", NULL),
							  g_lpConfig->GetSetting("sslkey_pass", "", NULL));
	if (hr != hrSuccess) {
		g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Unable to open admin session. Error 0x%08X", hr);
		goto exit;
	}

	if (disconnects == 0)
		g_lpLogger->Log(EC_LOGLEVEL_DEBUG, "Connection to Zarafa server succeeded");
	else
		g_lpLogger->Log(EC_LOGLEVEL_INFO, "Connection to Zarafa server succeeded after %d retries", disconnects);

	disconnects = 0;			// first call succeeded, assume all is well.

	hr = GetAdminSpooler(lpAdminSession, &lpSpooler);
	if (hr != hrSuccess) {
		g_lpLogger->Log(EC_LOGLEVEL_ERROR, "ProcessQueue: GetAdminSpooler failed %x", hr);
		goto exit;
	}

	// Mark reload as done since we reloaded the outgoing table
	nReload = false;
	
	// Request the master outgoing table
	hr = lpSpooler->GetMasterOutgoingTable(0, &lpTable);
	if (hr != hrSuccess) {
		g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Master outgoing queue not available");
		goto exit;
	}

	hr = lpTable->SetColumns((LPSPropTagArray)&sOutgoingCols, 0);
	if (hr != hrSuccess) {
		g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Unable to setColumns() on OutgoingQueue");
		goto exit;
	}
	
	// Sort by ascending hierarchyid: first in, first out queue
	hr = lpTable->SortTable(&sSort, 0);
	if (hr != hrSuccess) {
		g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Unable to SortTable() on OutgoingQueue");
		goto exit;
	}

	hr = HrAllocAdviseSink(AdviseCallback, NULL, &lpAdviseSink);	
	if (hr != hrSuccess) {
		g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Unable to allocate memory for advise sink");
		goto exit;
	}

	// notify on new mail in the outgoing table
	hr = lpTable->Advise(fnevTableModified, lpAdviseSink, &ulConnection);

	while(!bQuit && !nReload) {
		bMessagesWaiting = false;

		lpTable->SeekRow(BOOKMARK_BEGINNING, 0, NULL);

		// also checks not to send a message again which is already sending
		hr = ProcessAllEntries(lpAdminSession, lpSpooler, lpTable, szSMTP, ulPort, szPath);
		if(hr != hrSuccess) {
			g_lpLogger->Log(EC_LOGLEVEL_WARNING, "ProcessQueue: ProcessAllEntries failed %x", hr);
			goto exit;
		}

		// Exit signal, break the operation
		if(bQuit)
			break;
			
		if(nReload)
			break;

		pthread_mutex_lock(&hMutexMessagesWaiting);
		if(!bMessagesWaiting) {
			struct timespec timeout;
			struct timeval now;

			// Wait for max 60 sec, then run queue anyway
			gettimeofday(&now,NULL);
			timeout.tv_sec = now.tv_sec + 60;
			timeout.tv_nsec = now.tv_usec * 1000;

			while (!bMessagesWaiting) {
				if (pthread_cond_timedwait(&hCondMessagesWaiting, &hMutexMessagesWaiting, &timeout) == ETIMEDOUT || bMessagesWaiting || bQuit || nReload)
					break;

				// not timed out, no messages waiting, not quit requested, no table reload required:
				// we were triggered for a cleanup call.
				CleanFinishedMessages(lpAdminSession, lpSpooler);
			}
		}
		pthread_mutex_unlock(&hMutexMessagesWaiting);

		// remove any entries that were done during the wait
		CleanFinishedMessages(lpAdminSession, lpSpooler);
	}

exit:
	// when we exit, we must make sure all forks started are cleaned
	if (bQuit) {
		ULONG ulCount = 0;
		ULONG ulThreads = 0;

		while (ulCount < 60) {
			if ((ulCount % 5) == 0) {
				ulThreads = mapSendData.size();
				g_lpLogger->Log(EC_LOGLEVEL_WARNING, "Still waiting for %d thread%c to exit.", ulThreads, ulThreads!=1?'s':' ');
			}

			CleanFinishedMessages(lpAdminSession, lpSpooler);

			if (mapSendData.size() == 0)
				break;

			Sleep(1000);
			ulCount++;
		}
		if (ulCount == 60)
			g_lpLogger->Log(EC_LOGLEVEL_DEBUG, "%d threads did not yet exit, closing anyway.", (int)mapSendData.size());
	} else if (nReload) {
		g_lpLogger->Log(EC_LOGLEVEL_WARNING, "Table reload requested, breaking server connection");
	}

	if (lpTable && ulConnection)
		lpTable->Unadvise(ulConnection);

	if (lpAdviseSink)
		lpAdviseSink->Release();

	if (lpTable)
		lpTable->Release();

	if (lpSpooler)
		lpSpooler->Release();

	if (lpAdminSession)
		lpAdminSession->Release();

	return hr;
}