|
|
//+--------------------------------------------------------------------------
//
// Copyright (c) 1997-1999 Microsoft Corporation
//
// File: wkstore.cpp
//
// Contents: Persistent job store routine.
//
// History:
//
//---------------------------------------------------------------------------
#include "pch.cpp"
#include "server.h"
#include "jobmgr.h"
#include "tlsjob.h"
#include "wkstore.h"
#include "debug.h"
WORKOBJECTINITFUNC g_WorkObjectInitFunList[] = { {WORKTYPE_RETURN_LICENSE, InitializeCReturnWorkObject } };
DWORD g_NumWorkObjectInitFunList = sizeof(g_WorkObjectInitFunList) / sizeof(g_WorkObjectInitFunList[0]);
//---------------------------------------------------
//
CLASS_PRIVATE CWorkObject* CPersistentWorkStorage::InitializeWorkObject( IN DWORD dwWorkType, IN PBYTE pbData, IN DWORD cbData ) /*++
--*/ { DBGPrintf( DBG_INFORMATION, DBG_FACILITY_WORKMGR, DBGLEVEL_FUNCTION_TRACE, _TEXT("CPersistentWorkStorage::InitializeWorkObject() initializing work %d\n"), dwWorkType );
CWorkObject* ptr = NULL; DWORD dwStatus = ERROR_SUCCESS;
try { for(DWORD index =0; index < g_NumWorkObjectInitFunList; index ++) { if(dwWorkType == g_WorkObjectInitFunList[index].m_WorkType) { ptr = (g_WorkObjectInitFunList[index].m_WorkInitFunc)( GetWorkManager(), pbData, cbData );
break; } }
if(index >= g_NumWorkObjectInitFunList) { SetLastError(dwStatus = TLS_E_WORKSTORAGE_UNKNOWNWORKTYPE); } else { TLSWorkManagerSetJobDefaults(ptr); } } catch( SE_Exception e ) { SetLastError(dwStatus = e.getSeNumber());
TLSLogEvent( EVENTLOG_ERROR_TYPE, TLS_E_WORKMANAGERGENERAL, TLS_E_WORKSTORAGE_INITWORK, dwWorkType, dwStatus );
} catch(...) {
SetLastError(dwStatus = TLS_E_WORKSTORAGE_INITWORKUNKNOWN);
TLSLogEvent( EVENTLOG_ERROR_TYPE, TLS_E_WORKMANAGERGENERAL, TLS_E_WORKSTORAGE_INITWORKUNKNOWN, dwWorkType ); }
if(dwStatus != ERROR_SUCCESS) { DBGPrintf( DBG_ERROR, DBG_FACILITY_WORKMGR, DBGLEVEL_FUNCTION_DETAILSIMPLE, _TEXT("CPersistentWorkStorage::InitializeWorkObject() return 0x%08x\n"), dwStatus ); }
return ptr; }
//---------------------------------------------------
//
CLASS_PRIVATE BOOL CPersistentWorkStorage::DeleteWorkObject( IN OUT CWorkObject* ptr ) /*++
--*/ { DWORD dwStatus = ERROR_SUCCESS; DWORD dwWorkType = 0;
DBGPrintf( DBG_INFORMATION, DBG_FACILITY_WORKMGR, DBGLEVEL_FUNCTION_TRACE, _TEXT("CPersistentWorkStorage::DeleteWorkObject() deleting work %s\n"), ptr->GetJobDescription() );
try { dwWorkType = ptr->GetWorkType(); ptr->SelfDestruct(); } catch( SE_Exception e ) { SetLastError(dwStatus = e.getSeNumber()); TLSLogEvent( EVENTLOG_ERROR_TYPE, TLS_E_WORKMANAGERGENERAL, TLS_E_WORKSTORAGE_DELETEWORK, dwWorkType, dwStatus ); } catch(...) {
SetLastError(dwStatus = TLS_E_WORKSTORAGE_DELETEWORKUNKNOWN); TLSLogEvent( EVENTLOG_ERROR_TYPE, TLS_E_WORKMANAGERGENERAL, TLS_E_WORKSTORAGE_DELETEWORKUNKNOWN, dwWorkType );
}
if(dwStatus != ERROR_SUCCESS) { DBGPrintf( DBG_ERROR, DBG_FACILITY_WORKMGR, DBGLEVEL_FUNCTION_DETAILSIMPLE, _TEXT("CPersistentWorkStorage::DeleteWorkObject() return 0x%08x\n"), dwStatus ); }
return dwStatus == ERROR_SUCCESS; }
//---------------------------------------------------
//
CPersistentWorkStorage::CPersistentWorkStorage( IN WorkItemTable* pWkItemTable ) : m_pWkItemTable(pWkItemTable), m_dwNumJobs(0), m_dwJobsInProcesssing(0), m_dwNextJobTime(INFINITE), m_pNextWorkObject(NULL) /*++
--*/ { }
//---------------------------------------------------
//
CPersistentWorkStorage::~CPersistentWorkStorage() { // just make sure we have shutdown
// TLSASSERT(m_pWkItemTable == NULL);
}
//---------------------------------------------------
//
BOOL CPersistentWorkStorage::DeleteErrorJob( IN CWorkObject* ptr ) /*++
--*/ { BOOL bSuccess = TRUE; DWORD dwStatus = ERROR_SUCCESS; PBYTE pbBookmark; DWORD cbBookmark; DWORD dwTime; DWORD dwJobType;
if(IsValidWorkObject(ptr) == FALSE) { SetLastError(dwStatus = ERROR_INVALID_PARAMETER); goto cleanup; }
bSuccess = ptr->GetJobId(&pbBookmark, &cbBookmark); if(bSuccess == FALSE) { SetLastError(dwStatus = ERROR_INVALID_DATA); goto cleanup; }
dwJobType = ptr->GetWorkType();
m_hTableLock.Lock();
bSuccess = UpdateWorkItemEntry( m_pWkItemTable, WORKITEM_DELETE, pbBookmark, cbBookmark, INFINITE, INFINITE, dwJobType, NULL, 0 );
if(bSuccess == FALSE) { dwStatus = GetLastError(); } m_hTableLock.UnLock(); DeleteWorkObject(ptr);
cleanup:
return bSuccess; }
//---------------------------------------------------
//
CLASS_PRIVATE DWORD CPersistentWorkStorage::GetCurrentBookmark( IN WorkItemTable* pTable, IN PBYTE pbData, IN OUT PDWORD pcbData ) /*++
--*/ { BOOL bSuccess = TRUE; DWORD dwStatus = ERROR_SUCCESS;
if(pTable != NULL) { JET_ERR jbError; bSuccess = pTable->GetBookmark(pbData, pcbData); if(bSuccess == FALSE) { jbError = pTable->GetLastJetError(); if(jbError == JET_errNoCurrentRecord) { *pcbData = 0; SetLastError(dwStatus = ERROR_NO_DATA); } else if(jbError == JET_errBufferTooSmall) { SetLastError(dwStatus = ERROR_INSUFFICIENT_BUFFER); } else { SetLastError(dwStatus = SET_JB_ERROR(jbError)); } } } else { SetLastError(dwStatus = ERROR_INVALID_PARAMETER); TLSASSERT(FALSE); }
return dwStatus; }
//-------------------------------------------------------------
//
CLASS_PRIVATE DWORD CPersistentWorkStorage::GetCurrentBookmarkEx( IN WorkItemTable* pTable, IN OUT PBYTE* ppbData, IN OUT PDWORD pcbData ) /*++
--*/ { DWORD dwStatus = ERROR_SUCCESS; BOOL bSucess = TRUE;
if(ppbData == NULL || pcbData == NULL || pTable == 0) { SetLastError(dwStatus = ERROR_INVALID_PARAMETER); return dwStatus; }
*ppbData = NULL; *pcbData = 0;
dwStatus = GetCurrentBookmark( pTable, *ppbData, pcbData );
if(dwStatus == ERROR_INSUFFICIENT_BUFFER) { *ppbData = (PBYTE)AllocateMemory(*pcbData); if(*ppbData != NULL) { dwStatus = GetCurrentBookmark( pTable, *ppbData, pcbData ); } }
if(dwStatus != ERROR_SUCCESS) { if(*ppbData != NULL) { FreeMemory(*ppbData); }
*ppbData = NULL; *pcbData = 0; }
return dwStatus; }
//------------------------------------------------------
CLASS_PRIVATE DWORD CPersistentWorkStorage::SetCurrentBookmark( IN WorkItemTable* pTable, IN PBYTE pbData, IN DWORD cbData ) /*++
--*/ { BOOL bSuccess; DWORD dwStatus = ERROR_SUCCESS;
if(pTable != NULL && pbData != NULL && cbData != 0) { bSuccess = pTable->GotoBookmark(pbData, cbData); if(bSuccess == FALSE) { if(pTable->GetLastJetError() == JET_errRecordDeleted) { SetLastError(dwStatus = ERROR_NO_DATA); } else { SetLastError(dwStatus = SET_JB_ERROR(pTable->GetLastJetError())); } } } else { SetLastError(dwStatus = ERROR_INVALID_PARAMETER); TLSASSERT(FALSE); }
return dwStatus; }
//---------------------------------------------------
//
BOOL CPersistentWorkStorage::Shutdown() { BOOL bSuccess = TRUE;
//
// CWorkManager will make sure
// no job is in processing state before calling this
// routine and no job can be scheduled.
//
m_hTableLock.Lock();
//
// Timing.
//
TLSASSERT(m_dwJobsInProcesssing == 0);
if(m_pWkItemTable != NULL) { bSuccess = m_pWkItemTable->CloseTable(); m_pWkItemTable = NULL; }
TLSASSERT(bSuccess == TRUE); m_pWkItemTable = NULL; m_dwNumJobs = 0; m_dwNextJobTime = INFINITE;
if(m_pNextWorkObject != NULL) { DeleteWorkObject( m_pNextWorkObject ); m_pNextWorkObject = NULL; }
m_hTableLock.UnLock(); return bSuccess; }
//---------------------------------------------------
//
DWORD CPersistentWorkStorage::StartupUpdateExistingJobTime() { BOOL bSuccess; DWORD dwStatus = ERROR_SUCCESS; DWORD dwTime; DWORD dwMinTime = INFINITE;
// CWorkObject* ptr = NULL;
BOOL bValidJob = TRUE; DWORD dwCurrentTime; m_hTableLock.Lock(); //
//
bSuccess = m_pWkItemTable->MoveToRecord(JET_MoveFirst); if(bSuccess == FALSE) { SetLastError(dwStatus = SET_JB_ERROR(m_pWkItemTable->GetLastJetError())); }
while(dwStatus == ERROR_SUCCESS) { WORKITEMRECORD wkItem;
//if(ptr != NULL)
//{
// DeleteWorkObject(ptr);
// ptr = NULL;
//}
bValidJob = FALSE;
//
// fetch the record
//
bSuccess = m_pWkItemTable->FetchRecord(wkItem); if(bSuccess == FALSE) { SetLastError(dwStatus = SET_JB_ERROR(m_pWkItemTable->GetLastJetError())); continue; }
if(wkItem.dwRestartTime != INFINITE && wkItem.dwScheduledTime >= m_dwStartupTime) { if(wkItem.dwScheduledTime < dwMinTime) { dwMinTime = wkItem.dwScheduledTime; }
break; }
//
// invalid data
//
if(wkItem.cbData != 0 && wkItem.pbData != NULL) { if(wkItem.dwRestartTime != INFINITE) { wkItem.dwScheduledTime = wkItem.dwRestartTime + time(NULL); wkItem.dwJobType &= ~WORKTYPE_PROCESSING; bSuccess = m_pWkItemTable->UpdateRecord( wkItem, WORKITEM_PROCESS_JOBTIME | WORKITEM_PROCESS_JOBTYPE ); if(bSuccess == FALSE) { SetLastError(dwStatus = SET_JB_ERROR(m_pWkItemTable->GetLastJetError())); break; }
if(wkItem.dwScheduledTime < dwMinTime) { dwMinTime = wkItem.dwScheduledTime; }
bValidJob = TRUE; } }
if(bValidJob == FALSE) { m_pWkItemTable->DeleteRecord(); }
// move the record pointer
bSuccess = m_pWkItemTable->MoveToRecord(); if(bSuccess == FALSE) { JET_ERR jetErrCode;
jetErrCode = m_pWkItemTable->GetLastJetError(); if(jetErrCode != JET_errNoCurrentRecord) { SetLastError(dwStatus = SET_JB_ERROR(jetErrCode)); }
break; } }
if(dwStatus == ERROR_SUCCESS) { bSuccess = m_pWkItemTable->MoveToRecord(JET_MoveFirst); if(bSuccess == FALSE) { SetLastError(dwStatus = SET_JB_ERROR(m_pWkItemTable->GetLastJetError())); }
UpdateNextJobTime(dwMinTime); }
m_hTableLock.UnLock();
//if(ptr != NULL)
//{
// DeleteWorkObject(ptr);
// ptr = NULL;
//}
return dwStatus; }
//---------------------------------------------------
//
BOOL CPersistentWorkStorage::Startup( IN CWorkManager* pWkMgr ) /*++
--*/ { BOOL bSuccess; DWORD dwStatus = ERROR_SUCCESS;
CWorkStorage::Startup(pWkMgr);
if(IsGood() == TRUE) { //
// loop thru all workitem and count number of job
//
m_hTableLock.Lock();
try { m_dwStartupTime = time(NULL);
//
// Get number of job in queue
//
//
// GetCount() will set index to time column
m_dwNumJobs = m_pWkItemTable->GetCount( FALSE, 0, NULL ); if(m_dwNumJobs == 0) { UpdateNextJobTime(INFINITE); } else { bSuccess = m_pWkItemTable->BeginTransaction(); if(bSuccess == TRUE) { dwStatus = StartupUpdateExistingJobTime(); if(dwStatus == ERROR_SUCCESS) { m_pWkItemTable->CommitTransaction(); } else { m_pWkItemTable->RollbackTransaction(); } } else { dwStatus = GetLastError(); }
//
// constructor set next job time to 0 so
// work manager will immediately try to find next job
//
// Move to first record in table
//bSuccess = m_pWkItemTable->MoveToRecord(JET_MoveFirst);
} } catch( SE_Exception e ) { SetLastError(dwStatus = e.getSeNumber()); } catch(...) { SetLastError(dwStatus = TLS_E_WORKMANAGER_INTERNAL); }
m_hTableLock.UnLock(); } else { SetLastError(dwStatus = ERROR_INVALID_PARAMETER); }
return (dwStatus == ERROR_SUCCESS); }
//----------------------------------------------------
//
CLASS_PRIVATE BOOL CPersistentWorkStorage::IsValidWorkObject( CWorkObject* ptr ) /*++
--*/ { BOOL bSuccess = FALSE; DWORD dwJobType; PBYTE pbData; DWORD cbData;
//
// Validate input parameter
//
if(ptr == NULL) { TLSASSERT(FALSE); goto cleanup; }
dwJobType = ptr->GetWorkType(); if(dwJobType == WORK_TYPE_UNKNOWN) { TLSASSERT(FALSE); goto cleanup; } ptr->GetWorkObjectData(&pbData, &cbData); if(pbData == NULL || cbData == 0) { TLSASSERT(pbData != NULL && cbData != NULL); goto cleanup; }
bSuccess = TRUE;
cleanup:
return bSuccess; }
//----------------------------------------------------
//
BOOL CPersistentWorkStorage::IsGood() { if( m_pWkItemTable == NULL || m_hTableLock.IsGood() == FALSE || GetWorkManager() == NULL ) { return FALSE; }
return m_pWkItemTable->IsValid(); }
//----------------------------------------------------
//
CLASS_PRIVATE BOOL CPersistentWorkStorage::UpdateJobEntry( IN WorkItemTable* pTable, IN PBYTE pbBookmark, IN DWORD cbBookmark, IN WORKITEMRECORD& wkItem ) /*++
--*/ { BOOL bSuccess = TRUE; DWORD dwStatus = ERROR_SUCCESS;
dwStatus = SetCurrentBookmark( pTable, pbBookmark, cbBookmark );
if(dwStatus == ERROR_SUCCESS) { bSuccess = pTable->UpdateRecord(wkItem); } else { bSuccess = FALSE; TLSASSERT(dwStatus == ERROR_SUCCESS); }
return bSuccess; }
//----------------------------------------------------
//
CLASS_PRIVATE BOOL CPersistentWorkStorage::AddJobEntry( IN WorkItemTable* pTable, IN WORKITEMRECORD& wkItem ) /*++
--*/ { BOOL bSuccess;
bSuccess = pTable->InsertRecord(wkItem); if(bSuccess == TRUE) { m_dwNumJobs++; }
return bSuccess; }
//----------------------------------------------------
//
CLASS_PRIVATE BOOL CPersistentWorkStorage::DeleteJobEntry( IN WorkItemTable* pTable, IN PBYTE pbBookmark, IN DWORD cbBookmark, IN WORKITEMRECORD& wkItem ) /*++
--*/ { BOOL bSuccess = TRUE; DWORD dwStatus = ERROR_SUCCESS;
dwStatus = SetCurrentBookmark( pTable, pbBookmark, cbBookmark );
if(dwStatus == ERROR_SUCCESS) { bSuccess = pTable->DeleteRecord();
if(bSuccess == TRUE) { m_dwNumJobs--; } } else { bSuccess = FALSE; TLSASSERT(dwStatus == ERROR_SUCCESS); }
return bSuccess; } //----------------------------------------------------
//
CLASS_PRIVATE BOOL CPersistentWorkStorage::UpdateWorkItemEntry( IN WorkItemTable* pTable, IN WORKITEM_OPERATION opCode, IN PBYTE pbBookmark, IN DWORD cbBookmark, IN DWORD dwRestartTime, IN DWORD dwTime, IN DWORD dwJobType, IN PBYTE pbJobData, IN DWORD cbJobData ) /*++
--*/ { BOOL bSuccess = TRUE; DWORD dwStatus = ERROR_SUCCESS; WORKITEMRECORD item; PBYTE pbCurrentBookmark=NULL; DWORD cbCurrentBookmark=0;
m_hTableLock.Lock();
dwStatus = GetCurrentBookmarkEx( pTable, &pbCurrentBookmark, &cbCurrentBookmark );
if(dwStatus != ERROR_SUCCESS && dwStatus != ERROR_NO_DATA) { goto cleanup; }
bSuccess = pTable->BeginTransaction(); if(bSuccess == FALSE) { dwStatus = GetLastError(); goto cleanup; }
item.dwScheduledTime = dwTime; item.dwRestartTime = dwRestartTime; item.dwJobType = dwJobType; item.cbData = cbJobData; item.pbData = pbJobData;
switch(opCode) { case WORKITEM_ADD: TLSASSERT(cbJobData != 0 && pbJobData != NULL); m_pWkItemTable->SetInsertRepositionBookmark( (dwTime < (DWORD)m_dwNextJobTime) );
bSuccess = AddJobEntry( pTable, item );
break;
case WORKITEM_BEGINPROCESSING: item.dwJobType |= WORKTYPE_PROCESSING; //
// FALL THRU
//
case WORKITEM_RESCHEDULE: TLSASSERT(cbJobData != 0 && pbJobData != NULL); bSuccess = UpdateJobEntry( pTable, pbBookmark, cbBookmark, item ); break;
case WORKITEM_DELETE: bSuccess = DeleteJobEntry( pTable, pbBookmark, cbBookmark, item ); break;
default:
TLSASSERT(FALSE); bSuccess = FALSE; }
if(bSuccess == TRUE) { pTable->CommitTransaction(); dwStatus = ERROR_SUCCESS;
//
// constructor set time to first job 0 so that work manager can immediate kick off
//
if( (opCode != WORKITEM_ADD && opCode != WORKITEM_RESCHEDULE) || dwTime > (DWORD)m_dwNextJobTime ) { if(pbCurrentBookmark != NULL && cbCurrentBookmark != 0) { dwStatus = SetCurrentBookmark( pTable, pbCurrentBookmark, cbCurrentBookmark );
if(dwStatus == ERROR_NO_DATA) { // record already deleted
dwStatus = ERROR_SUCCESS; } else { TLSASSERT(dwStatus == ERROR_SUCCESS); } } } else { UpdateNextJobTime(dwTime); } } else { SetLastError(dwStatus = SET_JB_ERROR(pTable->GetLastJetError())); pTable->RollbackTransaction(); TLSASSERT(FALSE); }
cleanup:
m_hTableLock.UnLock();
if(pbCurrentBookmark != NULL) { FreeMemory(pbCurrentBookmark); }
//
// WORKITEMRECORD will try to cleanup memory
//
item.pbData = NULL; item.cbData = 0;
return dwStatus == ERROR_SUCCESS; } //----------------------------------------------------
//
BOOL CPersistentWorkStorage::AddJob( IN DWORD dwTime, IN CWorkObject* ptr ) /*++
--*/ { DWORD dwStatus = ERROR_SUCCESS; BOOL bSuccess = TRUE; PBYTE pbData; DWORD cbData;
DBGPrintf( DBG_INFORMATION, DBG_FACILITY_WORKMGR, DBGLEVEL_FUNCTION_TRACE, _TEXT("CPersistentWorkStorage::AddJob() scheduling job %s at time %d\n"), ptr->GetJobDescription(), dwTime );
if(IsValidWorkObject(ptr) == FALSE) { SetLastError(dwStatus = ERROR_INVALID_PARAMETER); goto cleanup; }
bSuccess = ptr->GetWorkObjectData(&pbData, &cbData); if(bSuccess == FALSE) { SetLastError(dwStatus = ERROR_INVALID_PARAMETER); goto cleanup; }
m_hTableLock.Lock();
if(m_pWkItemTable != NULL) { bSuccess = UpdateWorkItemEntry( m_pWkItemTable, WORKITEM_ADD, NULL, 0, ptr->GetJobRestartTime(), dwTime + time(NULL), ptr->GetWorkType(), pbData, cbData );
if(bSuccess == FALSE) { dwStatus = GetLastError(); } } m_hTableLock.UnLock();
cleanup:
// Let Calling function delete it.
// DeleteWorkObject(ptr);
return dwStatus == ERROR_SUCCESS; }
//----------------------------------------------------
//
BOOL CPersistentWorkStorage::RescheduleJob( CWorkObject* ptr ) /*++
--*/ { BOOL bSuccess = TRUE; DWORD dwStatus = ERROR_SUCCESS; PBYTE pbData; DWORD cbData; PBYTE pbBookmark; DWORD cbBookmark; DWORD dwTime; DWORD dwJobType;
DBGPrintf( DBG_INFORMATION, DBG_FACILITY_WORKMGR, DBGLEVEL_FUNCTION_TRACE, _TEXT("CPersistentWorkStorage::RescheduleJob() scheduling job %s\n"), ptr->GetJobDescription() );
if(IsValidWorkObject(ptr) == FALSE) { SetLastError(dwStatus = ERROR_INVALID_PARAMETER); goto cleanup; }
bSuccess = ptr->GetWorkObjectData(&pbData, &cbData); if(bSuccess == FALSE) { SetLastError(dwStatus = ERROR_INVALID_DATA); goto cleanup; }
bSuccess = ptr->GetJobId(&pbBookmark, &cbBookmark); if(bSuccess == FALSE) { SetLastError(dwStatus = ERROR_INVALID_DATA); goto cleanup; } dwTime = ptr->GetSuggestedScheduledTime(); dwJobType = ptr->GetWorkType();
m_hTableLock.Lock();
if(m_pWkItemTable != NULL) { bSuccess = UpdateWorkItemEntry( m_pWkItemTable, (dwTime == INFINITE) ? WORKITEM_DELETE : WORKITEM_RESCHEDULE, pbBookmark, cbBookmark, ptr->GetJobRestartTime(), (dwTime == INFINITE) ? dwTime : dwTime + time(NULL), dwJobType, pbData, cbData );
if(bSuccess == FALSE) { dwStatus = GetLastError(); } } m_hTableLock.UnLock();
cleanup:
DeleteWorkObject(ptr); return dwStatus == ERROR_SUCCESS; }
//----------------------------------------------------
//
CLASS_PRIVATE DWORD CPersistentWorkStorage::FindNextJob() { DWORD dwStatus = ERROR_SUCCESS; BOOL bSuccess = TRUE; CWorkObject* ptr = NULL; JET_ERR jetErrCode; PBYTE pbBookmark = NULL; DWORD cbBookmark = 0;
m_hTableLock.Lock();
while(dwStatus == ERROR_SUCCESS) { WORKITEMRECORD wkItem;
// move the record pointer
bSuccess = m_pWkItemTable->MoveToRecord(); if(bSuccess == FALSE) { jetErrCode = m_pWkItemTable->GetLastJetError(); if(jetErrCode == JET_errNoCurrentRecord) { // end of table
UpdateNextJobTime(INFINITE); SetLastError(dwStatus = ERROR_NO_DATA); continue; } }
//
// fetch the record
//
bSuccess = m_pWkItemTable->FetchRecord(wkItem); if(bSuccess == FALSE) { SetLastError(dwStatus = SET_JB_ERROR(m_pWkItemTable->GetLastJetError())); continue; }
if(wkItem.dwJobType & WORKTYPE_PROCESSING) { // job is been processed, move to next one.
continue; }
dwStatus = GetCurrentBookmarkEx( m_pWkItemTable, &pbBookmark, &cbBookmark );
if(dwStatus != ERROR_SUCCESS) { // Error...
TLSASSERT(dwStatus == ERROR_SUCCESS); UpdateNextJobTime(INFINITE); break; }
if(wkItem.dwScheduledTime > m_dwStartupTime) { if(pbBookmark != NULL && cbBookmark != 0) { FreeMemory( pbBookmark ); pbBookmark = NULL; cbBookmark = 0; }
UpdateNextJobTime(wkItem.dwScheduledTime); break; }
//
// job is in queue before system startup, re-schedule
//
ptr = InitializeWorkObject( wkItem.dwJobType, wkItem.pbData, wkItem.cbData );
if(ptr == NULL) { if(pbBookmark != NULL && cbBookmark != 0) { FreeMemory( pbBookmark ); pbBookmark = NULL; cbBookmark = 0; }
//
// something is wrong, delete this job
// and move on to next job
//
m_pWkItemTable->DeleteRecord(); continue; }
//
// Set Job's storage ID and re-schedule this job
//
ptr->SetJobId(pbBookmark, cbBookmark); bSuccess = RescheduleJob(ptr); if(bSuccess == FALSE) { dwStatus = GetLastError(); }
if(pbBookmark != NULL && cbBookmark != 0) { FreeMemory( pbBookmark ); pbBookmark = NULL; cbBookmark = 0; } }
m_hTableLock.UnLock();
return dwStatus; }
//----------------------------------------------------
//
CLASS_PRIVATE CWorkObject* CPersistentWorkStorage::GetCurrentJob( PDWORD pdwTime ) /*++
--*/ { DWORD dwStatus = ERROR_SUCCESS; BOOL bSuccess = TRUE; WORKITEMRECORD wkItem; CWorkObject* ptr = NULL;
PBYTE pbBookmark=NULL; DWORD cbBookmark=0;
TLSASSERT(IsGood() == TRUE);
m_hTableLock.Lock(); while(dwStatus == ERROR_SUCCESS) { //
// fetch the record
//
bSuccess = m_pWkItemTable->FetchRecord(wkItem); TLSASSERT(bSuccess == TRUE); //TLSASSERT(!(wkItem.dwJobType & WORKTYPE_PROCESSING));
if(bSuccess == FALSE) { SetLastError(dwStatus = SET_JB_ERROR(m_pWkItemTable->GetLastJetError())); break; }
if( wkItem.dwScheduledTime < m_dwStartupTime || wkItem.cbData == 0 || wkItem.pbData == NULL ) { // FindNextJob() move record pointer one position down
m_pWkItemTable->MoveToRecord(JET_MovePrevious); dwStatus = FindNextJob();
continue; }
if( wkItem.dwJobType & WORKTYPE_PROCESSING ) { dwStatus = FindNextJob(); continue; }
ptr = InitializeWorkObject( wkItem.dwJobType, wkItem.pbData, wkItem.cbData );
dwStatus = GetCurrentBookmarkEx( m_pWkItemTable, &pbBookmark, &cbBookmark ); if(dwStatus != ERROR_SUCCESS) { // something is wrong, free up memory
// and exit.
SetLastError(dwStatus);
// TLSASSERT(FALSE);
DeleteWorkObject(ptr); ptr = NULL;
// grab next job
dwStatus = FindNextJob(); continue; }
//
// Set Job's storage ID
//
ptr->SetJobId(pbBookmark, cbBookmark); //ptr->SetScheduledTime(wkItem.dwScheduledTime);
*pdwTime = wkItem.dwScheduledTime;
if(pbBookmark != NULL && cbBookmark != 0) { FreeMemory( pbBookmark ); pbBookmark = NULL; cbBookmark = 0; }
break; }
m_hTableLock.UnLock(); return ptr; } //-----------------------------------------------------
//
DWORD CPersistentWorkStorage::GetNextJobTime() { DWORD dwTime; dwTime = (DWORD)m_dwNextJobTime;
return dwTime; }
//-----------------------------------------------------
//
CWorkObject* CPersistentWorkStorage::GetNextJob( PDWORD pdwTime ) /*++
--*/ { CWorkObject* ptr = NULL;
if((DWORD)m_dwNextJobTime != INFINITE) { try { m_hTableLock.Lock();
//
// Fetch record where current bookmark points to,
// it is possible that new job arrived after
// WorkManager already calls GetNextJobTime(),
// this is OK since in this case this new job
// needs immediate processing.
//
ptr = GetCurrentJob(pdwTime);
//
// reposition current record pointer
//
FindNextJob(); } catch(...) { SetLastError(TLS_E_WORKMANAGER_INTERNAL); ptr = NULL; } m_hTableLock.UnLock(); }
return ptr; }
//-----------------------------------------------------
//
BOOL CPersistentWorkStorage::ReturnJobToQueue( IN DWORD dwTime, IN CWorkObject* ptr ) /*++
--*/ { DWORD dwStatus = ERROR_SUCCESS; PBYTE pbBookmark; DWORD cbBookmark; DWORD dwJobType; PBYTE pbData; DWORD cbData;
if(IsValidWorkObject(ptr) == FALSE) { SetLastError(dwStatus = ERROR_INVALID_PARAMETER); goto cleanup; }
if(ptr->IsWorkPersistent() == FALSE) { SetLastError(dwStatus = ERROR_INVALID_DATA); TLSASSERT(FALSE); goto cleanup; }
if(ptr->GetWorkObjectData(&pbData, &cbData) == FALSE) { SetLastError(dwStatus = ERROR_INVALID_DATA); goto cleanup; }
if(ptr->GetJobId(&pbBookmark, &cbBookmark) == FALSE) { SetLastError(dwStatus = ERROR_INVALID_DATA); goto cleanup; }
m_hTableLock.Lock();
if(dwTime < (DWORD)m_dwNextJobTime) { // Position current record
dwStatus = SetCurrentBookmark( m_pWkItemTable, pbBookmark, cbBookmark );
TLSASSERT(dwStatus == ERROR_SUCCESS); if(dwStatus == ERROR_SUCCESS) { UpdateNextJobTime(dwTime); } }
m_hTableLock.UnLock();
cleanup:
DeleteWorkObject(ptr);
return dwStatus == ERROR_SUCCESS; }
//-----------------------------------------------------
//
BOOL CPersistentWorkStorage::EndProcessingJob( IN ENDPROCESSINGJOB_CODE opCode, IN DWORD dwOriginalTime, IN CWorkObject* ptr ) /*++
Abstract:
Parameter:
opCode : End Processing code. ptr : Job has completed processing or been returned by workmanager due to time or resource constraint.
Return:
TRUE/FALSE
--*/ { BOOL bSuccess = TRUE; BYTE pbData = NULL; DWORD cbData = 0;
DBGPrintf( DBG_INFORMATION, DBG_FACILITY_WORKMGR, DBGLEVEL_FUNCTION_TRACE, _TEXT("CPersistentWorkStorage::EndProcessingJob() - end processing %s opCode %d\n"), ptr->GetJobDescription(), opCode );
if(ptr == NULL) { bSuccess = FALSE; SetLastError(ERROR_INVALID_PARAMETER); goto cleanup; }
if(ptr->IsWorkPersistent() == FALSE) { SetLastError(ERROR_INVALID_DATA); TLSASSERT(FALSE); goto cleanup; }
switch(opCode) { case ENDPROCESSINGJOB_SUCCESS: bSuccess = RescheduleJob(ptr); m_dwJobsInProcesssing--; break;
case ENDPROCESSINGJOB_ERROR: bSuccess = DeleteErrorJob(ptr); m_dwJobsInProcesssing--; break;
case ENDPROCESSINGJOB_RETURN: bSuccess = ReturnJobToQueue(dwOriginalTime, ptr); break;
default:
TLSASSERT(FALSE); }
cleanup: return bSuccess; }
//-------------------------------------------------------
//
BOOL CPersistentWorkStorage::BeginProcessingJob( IN CWorkObject* ptr ) /*++
Abstract:
Work Manager call this to inform. storage that this job is about to be processed.
Parameter:
ptr - Job to be process.
Return:
TRUE/FALSE
--*/ { BOOL bSuccess = TRUE; DWORD dwStatus = ERROR_SUCCESS; PBYTE pbBookmark; DWORD cbBookmark; DWORD dwTime; PBYTE pbData; DWORD cbData;
DBGPrintf( DBG_INFORMATION, DBG_FACILITY_WORKMGR, DBGLEVEL_FUNCTION_TRACE, _TEXT("CPersistentWorkStorage::BeginProcessingJob() - beginning processing %s\n"), ptr->GetJobDescription() );
if(IsValidWorkObject(ptr) == FALSE) { SetLastError(dwStatus = ERROR_INVALID_PARAMETER); goto cleanup; }
if(ptr->IsWorkPersistent() == FALSE) { SetLastError(dwStatus = ERROR_INVALID_DATA); TLSASSERT(FALSE); goto cleanup; }
bSuccess = ptr->GetWorkObjectData(&pbData, &cbData); if(bSuccess == FALSE) { SetLastError(dwStatus = ERROR_INVALID_DATA); goto cleanup; }
bSuccess = ptr->GetJobId(&pbBookmark, &cbBookmark); if(bSuccess == FALSE) { SetLastError(dwStatus = ERROR_INVALID_DATA); goto cleanup; }
m_hTableLock.Lock();
bSuccess = UpdateWorkItemEntry( m_pWkItemTable, WORKITEM_BEGINPROCESSING, pbBookmark, cbBookmark, ptr->GetJobRestartTime(), ptr->GetScheduledTime(), ptr->GetWorkType(), pbData, cbData );
if(bSuccess == TRUE) { m_dwJobsInProcesssing ++; } else { dwStatus = GetLastError(); } m_hTableLock.UnLock();
cleanup:
return dwStatus == ERROR_SUCCESS; }
|