123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- /*
- * Copyright 2005 - 2016 Zarafa and its licensors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- #include <kopano/platform.h>
- #include <utility>
- #include <kopano/ECScheduler.h>
- #include <kopano/lockhelper.hpp>
- #include <cerrno>
- #include <sys/time.h> /* gettimeofday */
- #define SCHEDULER_POLL_FREQUENCY 5
- namespace KC {
- ECScheduler::ECScheduler(ECLogger *lpLogger) :
- m_lpLogger(lpLogger)
- {
- m_lpLogger->AddRef();
- //Create Scheduler thread
- pthread_create(&m_hMainThread, NULL, ScheduleThread, (void*)this);
- set_thread_name(m_hMainThread, "ECScheduler:main");
- }
- ECScheduler::~ECScheduler(void)
- {
- ulock_normal l_exit(m_hExitMutex);
- m_bExit = TRUE;
- m_hExitSignal.notify_one();
- l_exit.unlock();
- pthread_join(m_hMainThread, NULL);
- //Clean up something
- m_lpLogger->Release();
- }
- HRESULT ECScheduler::AddSchedule(eSchedulerType eType, unsigned int ulBeginCycle, void* (*lpFunction)(void*), void* lpData)
- {
- scoped_rlock l_sched(m_hSchedulerMutex);
- if (lpFunction == NULL)
- return E_INVALIDARG;
- ECSCHEDULE sECSchedule;
- sECSchedule.eType = eType;
- sECSchedule.ulBeginCycle = ulBeginCycle;
- sECSchedule.lpFunction = lpFunction;
- sECSchedule.lpData = lpData;
- sECSchedule.tLastRunTime = 0;
- m_listScheduler.push_back(std::move(sECSchedule));
- return S_OK;
- }
- bool ECScheduler::hasExpired(time_t ttime, ECSCHEDULE *lpSchedule)
- {
- struct tm tmLastRunTime;
- struct tm tmtime;
- localtime_r(&ttime, &tmtime);
- if(lpSchedule->tLastRunTime > 0)
- localtime_r(&lpSchedule->tLastRunTime, &tmLastRunTime);
- else
- memset(&tmLastRunTime, 0, sizeof(tmLastRunTime));
- switch (lpSchedule->eType) {
- case SCHEDULE_SECONDS:
- return
- (((tmLastRunTime.tm_min != tmtime.tm_min) ||
- ((tmLastRunTime.tm_min == tmtime.tm_min) &&
- (tmLastRunTime.tm_sec != tmtime.tm_sec))) &&
- ((tmtime.tm_sec == (int)lpSchedule->ulBeginCycle) ||
- ((lpSchedule->ulBeginCycle > 0) &&
- ((tmtime.tm_sec % (int)lpSchedule->ulBeginCycle) < SCHEDULER_POLL_FREQUENCY))));
- case SCHEDULE_MINUTES:
- return
- (((tmLastRunTime.tm_hour != tmtime.tm_hour) ||
- ((tmLastRunTime.tm_hour == tmtime.tm_hour) &&
- (tmLastRunTime.tm_min != tmtime.tm_min))) &&
- ((tmtime.tm_min == (int)lpSchedule->ulBeginCycle) ||
- ((lpSchedule->ulBeginCycle > 0) &&
- ((tmtime.tm_min % (int)lpSchedule->ulBeginCycle) == 0))));
- case SCHEDULE_HOUR:
- return
- ((tmLastRunTime.tm_hour != tmtime.tm_hour) &&
- ((int)lpSchedule->ulBeginCycle >= tmtime.tm_min) &&
- ((int)lpSchedule->ulBeginCycle <= (tmtime.tm_min + 2)));
- case SCHEDULE_DAY:
- return
- ((tmLastRunTime.tm_mday != tmtime.tm_mday) &&
- ((int)lpSchedule->ulBeginCycle == tmtime.tm_hour));
- case SCHEDULE_MONTH:
- return
- ((tmLastRunTime.tm_mon != tmtime.tm_mon) &&
- ((int)lpSchedule->ulBeginCycle == tmtime.tm_mday));
- case SCHEDULE_NONE:
- return false;
- }
- return false;
- }
- void* ECScheduler::ScheduleThread(void* lpTmpScheduler)
- {
- ECScheduleList::iterator iterScheduleList;
- auto lpScheduler = static_cast<ECScheduler *>(lpTmpScheduler);
- HRESULT* lperThread = NULL;
- pthread_t hThread;
- time_t ttime;
- if (lpScheduler == NULL)
- return NULL;
- while(TRUE)
- {
- // Wait for a terminate signal or return after a few minutes
- ulock_normal l_exit(lpScheduler->m_hExitMutex);
- if (lpScheduler->m_bExit)
- break;
- if (lpScheduler->m_hExitSignal.wait_for(l_exit, std::chrono::seconds(SCHEDULER_POLL_FREQUENCY)) ==
- std::cv_status::timeout)
- break;
- l_exit.unlock();
- for (auto &sl : lpScheduler->m_listScheduler) {
- ulock_rec l_sched(lpScheduler->m_hSchedulerMutex);
- //TODO If load on server high, check only items with a high priority
- time(&ttime);
-
- if (hasExpired(ttime, &sl)) {
- //Create task thread
- int err = 0;
-
- if((err = pthread_create(&hThread, NULL, sl.lpFunction, static_cast<void *>(sl.lpData))) != 0) {
- lpScheduler->m_lpLogger->Log(EC_LOGLEVEL_FATAL, "Unable to spawn new thread: %s", strerror(err));
- goto task_fail;
- }
- set_thread_name(hThread, "ECScheduler:worker");
- sl.tLastRunTime = ttime;
- if((err = pthread_join(hThread, (void**)&lperThread)) != 0) {
- lpScheduler->m_lpLogger->Log(EC_LOGLEVEL_FATAL, "Unable to join thread: %s", strerror(err));
- goto task_fail;
- }
- delete lperThread;
- lperThread = NULL;
- }
- task_fail:
- l_sched.unlock();
- // check for a exit signal
- l_exit.lock();
- if(lpScheduler->m_bExit) {
- l_exit.unlock();
- break;
- }
- l_exit.unlock();
- }
- }
- return NULL;
- }
- } /* namespace */
|