Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1327 lines
28 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Copyright (c) 1997-1999 Microsoft Corporation
  4. //
  5. // File: jobmgr.h
  6. //
  7. // Contents:
  8. //
  9. // History:
  10. //
  11. //---------------------------------------------------------------------------
  12. #ifndef __WORKMANAGER_H__
  13. #define __WORKMANAGER_H__
  14. #include <new.h>
  15. #include <eh.h>
  16. #include "tlsstl.h"
  17. #include "dbgout.h"
  18. #include "locks.h"
  19. #include "tlsassrt.h"
  20. #include "license.h"
  21. #include "tlsapip.h"
  22. #include "tlspol.h"
  23. //
  24. // Default cancel timeout is 5 seconds
  25. //
  26. #define DEFAULT_RPCCANCEL_TIMEOUT 5
  27. //
  28. // Default interval time is 15 mins.
  29. //
  30. #define DEFAULT_WORK_INTERVAL 15*60*1000
  31. //
  32. // Default shutdown wait time
  33. //
  34. #define DEFAULT_SHUTDOWN_TIME 60*2*1000
  35. //
  36. // Max. Number of concurrent Jobs
  37. //
  38. #define DEFAULT_NUM_CONCURRENTJOB 50
  39. //
  40. //
  41. //
  42. #define WORKMANAGER_TIMER_PERIOD_TIMER 0xFFFFFFFF // see RtlUpdateTimer()
  43. #define WORKMANAGER_WAIT_FOREVER INFINITE
  44. #define CLASS_PRIVATE
  45. #define CLASS_STATIC
  46. class CWorkManager;
  47. class CWorkObject;
  48. #ifdef __TEST_WORKMGR__
  49. #define DBGCONSOLE GetStdHandle(STD_OUTPUT_HANDLE)
  50. #else
  51. #define DBGCONSOLE NULL
  52. #endif
  53. //--------------------------------------------------------------
  54. //
  55. // Work Object initialization function, each work object
  56. // must supply its own initialization routine to work
  57. // manager.
  58. //
  59. typedef enum {
  60. JOBDURATION_UNKNOWN=0,
  61. JOBDURATION_RUNONCE, // Run Once Work
  62. JOBDURATION_SESSION, // Session Job
  63. JOBDURATION_PERSISTENT // Persistent Job
  64. } JOBDURATION;
  65. #define JOB_SHORT_LIVE 0x00000001
  66. #define JOB_INCLUDES_IO 0x00000002
  67. #define JOB_LONG_RUNNING 0x00000004
  68. #define WORK_TYPE_UNKNOWN 0x00000000
  69. #ifndef AllocateMemory
  70. #define AllocateMemory(size) \
  71. LocalAlloc(LPTR, size)
  72. #endif
  73. #ifndef FreeMemory
  74. #define FreeMemory(ptr) \
  75. if(ptr) \
  76. { \
  77. LocalFree(ptr); \
  78. ptr=NULL; \
  79. }
  80. #endif
  81. #ifndef ReallocateMemory
  82. #define ReallocateMemory(ptr, size) \
  83. LocalReAlloc(ptr, size, LMEM_ZEROINIT)
  84. #endif
  85. //------------------------------------------------------
  86. //
  87. class MyCSemaphore {
  88. private:
  89. HANDLE m_semaphore;
  90. long m_TryEntry;
  91. long m_Acquired;
  92. long m_Max;
  93. public:
  94. MyCSemaphore() : m_semaphore(NULL), m_TryEntry(0), m_Acquired(0), m_Max(0) {}
  95. //--------------------------------------------------
  96. const long
  97. GetTryEntryCount() { return m_TryEntry; }
  98. //--------------------------------------------------
  99. const long
  100. GetAcquiredCount() { return m_Acquired; }
  101. //--------------------------------------------------
  102. const long
  103. GetMaxCount() { return m_Max; }
  104. //--------------------------------------------------
  105. BOOL
  106. Init(
  107. LONG lInitCount,
  108. LONG lMaxCount
  109. )
  110. /*++
  111. --*/
  112. {
  113. m_semaphore=CreateSemaphore(
  114. NULL,
  115. lInitCount,
  116. lMaxCount,
  117. NULL
  118. );
  119. m_Max = lMaxCount;
  120. m_TryEntry = 0;
  121. m_Acquired = 0;
  122. TLSASSERT(m_semaphore != NULL);
  123. return m_semaphore != NULL;
  124. }
  125. //--------------------------------------------------
  126. ~MyCSemaphore()
  127. {
  128. TLSASSERT(m_Acquired == 0);
  129. TLSASSERT(m_TryEntry == 0);
  130. if(m_semaphore)
  131. {
  132. CloseHandle(m_semaphore);
  133. }
  134. }
  135. //--------------------------------------------------
  136. BOOL
  137. AcquireEx(
  138. HANDLE hHandle,
  139. DWORD dwWaitTime=INFINITE,
  140. BOOL bAlertable=FALSE
  141. )
  142. /*++
  143. --*/
  144. {
  145. BOOL bSuccess = TRUE;
  146. DWORD dwStatus;
  147. HANDLE hHandles[] = {m_semaphore, hHandle};
  148. TLSASSERT(IsGood() == TRUE);
  149. if(hHandle == NULL || hHandle == INVALID_HANDLE_VALUE)
  150. {
  151. SetLastError(ERROR_INVALID_PARAMETER);
  152. bSuccess = FALSE;
  153. }
  154. else
  155. {
  156. InterlockedIncrement(&m_TryEntry);
  157. dwStatus = WaitForMultipleObjectsEx(
  158. sizeof(hHandles)/sizeof(hHandles[0]),
  159. hHandles,
  160. FALSE,
  161. dwWaitTime,
  162. bAlertable
  163. );
  164. if(dwStatus == WAIT_OBJECT_0)
  165. {
  166. InterlockedIncrement(&m_Acquired);
  167. }
  168. else
  169. {
  170. bSuccess = FALSE;
  171. }
  172. InterlockedDecrement(&m_TryEntry);
  173. }
  174. return bSuccess;
  175. }
  176. //--------------------------------------------------
  177. DWORD
  178. Acquire(
  179. DWORD dwWaitTime=INFINITE,
  180. BOOL bAlertable=FALSE
  181. )
  182. /*++
  183. --*/
  184. {
  185. DWORD dwStatus;
  186. TLSASSERT(IsGood() == TRUE);
  187. InterlockedIncrement(&m_TryEntry);
  188. dwStatus = WaitForSingleObjectEx(
  189. m_semaphore,
  190. dwWaitTime,
  191. bAlertable
  192. );
  193. if(dwStatus == WAIT_OBJECT_0)
  194. {
  195. InterlockedIncrement(&m_Acquired);
  196. }
  197. InterlockedDecrement(&m_TryEntry);
  198. return dwStatus;
  199. }
  200. //--------------------------------------------------
  201. BOOL
  202. Release(
  203. long count=1
  204. )
  205. /*++
  206. --*/
  207. {
  208. BOOL bSuccess;
  209. TLSASSERT(IsGood() == TRUE);
  210. bSuccess = ReleaseSemaphore(
  211. m_semaphore,
  212. count,
  213. NULL
  214. );
  215. if(bSuccess == TRUE)
  216. {
  217. InterlockedDecrement(&m_Acquired);
  218. }
  219. return bSuccess;
  220. }
  221. //--------------------------------------------------
  222. BOOL
  223. IsGood()
  224. /*++
  225. --*/
  226. {
  227. return m_semaphore != NULL;
  228. }
  229. //--------------------------------------------------
  230. const HANDLE
  231. GetHandle()
  232. {
  233. return m_semaphore;
  234. }
  235. };
  236. //-------------------------------------------------------------
  237. //
  238. // Pure virtual base class for CWorkManager to store persistent
  239. // work object.
  240. //
  241. typedef enum {
  242. ENDPROCESSINGJOB_RETURN=0, // unable to process job, wait for next term.
  243. ENDPROCESSINGJOB_SUCCESS, // job completed.
  244. ENDPROCESSINGJOB_ERROR // error in processing this job
  245. } ENDPROCESSINGJOB_CODE;
  246. class CWorkStorage {
  247. friend class CWorkManager;
  248. protected:
  249. CWorkManager* m_pWkMgr;
  250. public:
  251. CWorkStorage(
  252. CWorkManager* pWkMgr=NULL
  253. ) :
  254. m_pWkMgr(pWkMgr) {}
  255. ~CWorkStorage() {}
  256. //---------------------------------------------------
  257. CWorkManager*
  258. GetWorkManager() {
  259. return m_pWkMgr;
  260. }
  261. //---------------------------------------------------
  262. virtual BOOL
  263. Startup(
  264. IN CWorkManager* pWkMgr
  265. )
  266. /*++
  267. --*/
  268. {
  269. if(pWkMgr != NULL)
  270. {
  271. m_pWkMgr = pWkMgr;
  272. }
  273. else
  274. {
  275. SetLastError(ERROR_INVALID_PARAMETER);
  276. }
  277. return pWkMgr != NULL;
  278. }
  279. //---------------------------------------------------
  280. virtual BOOL
  281. Shutdown() = 0;
  282. virtual BOOL
  283. AddJob(
  284. IN DWORD dwTime, // relative to current time
  285. IN CWorkObject* ptr // Pointer to work object
  286. ) = 0;
  287. //virtual BOOL
  288. //JobEnumBegin(
  289. // DWORD dwLowScheduleTime=0,
  290. // DWORD dwHighScheduleTime=0
  291. //) = 0;
  292. //
  293. // Return time to next job
  294. virtual DWORD
  295. GetNextJobTime() = 0;
  296. //
  297. // return job to be processed next
  298. virtual CWorkObject*
  299. GetNextJob(PDWORD pdwTime) = 0;
  300. //
  301. // Inform storage that we are processing this job
  302. virtual BOOL
  303. BeginProcessingJob(
  304. IN CWorkObject* pJob
  305. ) = 0;
  306. // Inform storage that this job has completed
  307. virtual BOOL
  308. EndProcessingJob(
  309. IN ENDPROCESSINGJOB_CODE opCode,
  310. IN DWORD dwOriginalScheduledTime,
  311. IN CWorkObject* pJob
  312. ) = 0;
  313. //virtual BOOL
  314. //JobEnumEnd() = 0;
  315. virtual DWORD
  316. GetNumJobs() = 0;
  317. };
  318. //-------------------------------------------------------------
  319. //
  320. typedef struct _ScheduleJob {
  321. DWORD m_ulScheduleTime; // absolute time
  322. CWorkObject* m_pWorkObject;
  323. } SCHEDULEJOB, *PSCHEDULEJOB, *LPSCHEDULEJOB;
  324. inline bool
  325. operator<(
  326. const struct _ScheduleJob& a,
  327. const struct _ScheduleJob& b
  328. )
  329. /*++
  330. --*/
  331. {
  332. return a.m_ulScheduleTime < b.m_ulScheduleTime;
  333. }
  334. //-------------------------------------------------------------
  335. //
  336. // TODO : Re-design our in-memory job as a plugin like persistent
  337. // Job.
  338. //
  339. //-------------------------------------------------------------
  340. class CWorkManager {
  341. friend class CWorkObject;
  342. private:
  343. typedef struct {
  344. BOOL bProcessInMemory;
  345. CWorkManager* pWorkMgr;
  346. } WorkManagerProcessContext, *PWorkManagerProcessContext;
  347. //
  348. // Schedule job might be at the same time, so use multimap
  349. // TODO : Need to move this into template.
  350. //
  351. // All in memory job schedule time are in absolute time
  352. //
  353. typedef multimap<DWORD, CWorkObject* > SCHEDULEJOBMAP;
  354. SCHEDULEJOBMAP m_Jobs; // schedule jobs.
  355. CRWLock m_JobLock; // Schedule Job Lock
  356. typedef struct {
  357. long m_refCounter;
  358. HANDLE m_hThread;
  359. } WorkMangerInProcessJob;
  360. typedef map<PVOID, WorkMangerInProcessJob > INPROCESSINGJOBLIST;
  361. CCriticalSection m_InProcessingListLock;
  362. INPROCESSINGJOBLIST m_InProcessingList;
  363. HANDLE m_hJobInProcessing; // signal if no job, non-signal
  364. // if job currently in process
  365. HANDLE m_hWorkMgrThread;
  366. HANDLE m_hNewJobArrive;
  367. HANDLE m_hShutdown; // shutdown timer.
  368. HANDLE m_hInStorageWait;
  369. // relative time to next schedule job
  370. //CCriticalSection m_JobTimeLock;
  371. //CMyCounter m_dwNextInStorageJobTime;
  372. //CMyCounter m_dwNextInMemoryJobTime;
  373. CSafeCounter m_dwNextInStorageJobTime;
  374. CSafeCounter m_dwNextInMemoryJobTime;
  375. //DWORD m_dwNextInMemoryJobTime; // Absolute time.
  376. //DWORD m_dwNextInStorageJobTime; // Absolute time.
  377. long m_NumJobInProcess;
  378. //
  379. // Default interval to process job
  380. DWORD m_dwDefaultInterval;
  381. // Max. concurrent job, not use
  382. DWORD m_dwMaxCurrentJob;
  383. MyCSemaphore m_hMaxJobLock;
  384. CWorkStorage* m_pPersistentWorkStorage;
  385. private:
  386. //-------------------------------------------------------------
  387. DWORD
  388. AddJobToProcessingList(
  389. CWorkObject* ptr
  390. );
  391. //-------------------------------------------------------------
  392. DWORD
  393. RemoveJobFromProcessingList(
  394. CWorkObject* ptr
  395. );
  396. //-------------------------------------------------------------
  397. DWORD
  398. ProcessScheduledJob();
  399. //-------------------------------------------------------------
  400. BOOL
  401. SignalJobArrive() { return SetEvent(m_hNewJobArrive); }
  402. //-------------------------------------------------------------
  403. BOOL
  404. WaitForObjectOrShutdown(
  405. HANDLE hHandle
  406. );
  407. //-------------------------------------------------------------
  408. DWORD
  409. RunJob(
  410. IN CWorkObject* ptr,
  411. IN BOOL bImmediate
  412. );
  413. //-------------------------------------------------------------
  414. void
  415. EndProcessingScheduledJob(
  416. IN CWorkObject* ptr
  417. )
  418. /*++
  419. --*/
  420. {
  421. RemoveJobFromProcessingList(ptr);
  422. return;
  423. }
  424. //-------------------------------------------------------------
  425. void
  426. DeleteAllJobsInMemoryQueue();
  427. //-------------------------------------------------------------
  428. void
  429. CancelInProcessingJob();
  430. //-------------------------------------------------------------
  431. BOOL
  432. SignalJobRunning(
  433. CWorkObject* ptr
  434. );
  435. //-------------------------------------------------------------
  436. CWorkObject*
  437. GetNextJobInMemoryQueue(
  438. PDWORD pulTime
  439. );
  440. //-------------------------------------------------------------
  441. BOOL
  442. RemoveJobFromInMemoryQueue(
  443. IN DWORD ulJobTime,
  444. IN CWorkObject* ptr
  445. );
  446. //-------------------------------------------------------------
  447. DWORD
  448. AddJobIntoMemoryQueue(
  449. DWORD ulTime,
  450. CWorkObject* pWork
  451. );
  452. //-------------------------------------------------------------
  453. BOOL
  454. IsShuttingDown()
  455. {
  456. if(m_hShutdown == NULL)
  457. {
  458. return TRUE;
  459. }
  460. return (WaitForSingleObject( m_hShutdown, 0 ) == WAIT_OBJECT_0);
  461. }
  462. //-------------------------------------------------------------
  463. static DWORD WINAPI
  464. ProcessInMemoryScheduledJob(PVOID);
  465. //-------------------------------------------------------------
  466. static DWORD WINAPI
  467. ProcessInStorageScheduledJob(PVOID);
  468. //-------------------------------------------------------------
  469. static unsigned int __stdcall
  470. WorkManagerThread(PVOID);
  471. //-------------------------------------------------------------
  472. static DWORD WINAPI
  473. ExecuteWorkObject(PVOID);
  474. //-------------------------------------------------------------
  475. DWORD
  476. GetTimeToNextJob();
  477. //-------------------------------------------------------------
  478. void
  479. AddJobUpdateInMemoryJobWaitTimer(
  480. DWORD dwJobTime
  481. )
  482. /*++
  483. --*/
  484. {
  485. //m_JobTimeLock.Lock();
  486. if((DWORD)m_dwNextInMemoryJobTime > dwJobTime)
  487. {
  488. m_dwNextInMemoryJobTime = dwJobTime;
  489. }
  490. //m_JobTimeLock.UnLock();
  491. return;
  492. }
  493. //-------------------------------------------------------------
  494. void
  495. AddJobUpdateInStorageJobWaitTimer(
  496. DWORD dwJobTime
  497. )
  498. /*++
  499. --*/
  500. {
  501. //m_JobTimeLock.Lock();
  502. if((DWORD)m_dwNextInStorageJobTime > dwJobTime)
  503. {
  504. m_dwNextInStorageJobTime = dwJobTime;
  505. }
  506. //m_JobTimeLock.UnLock();
  507. return;
  508. }
  509. //-------------------------------------------------------------
  510. BOOL
  511. UpdateTimeToNextPersistentJob()
  512. /*++
  513. --*/
  514. {
  515. BOOL bSuccess = TRUE;
  516. //
  517. // Work Manager thread are processing storage job, don't
  518. // Update the storage job timer.
  519. //
  520. TLSASSERT(m_pPersistentWorkStorage != NULL);
  521. if(m_pPersistentWorkStorage->GetNumJobs() > 0)
  522. {
  523. m_dwNextInStorageJobTime = m_pPersistentWorkStorage->GetNextJobTime();
  524. }
  525. return bSuccess;
  526. }
  527. //------------------------------------------------------------
  528. BOOL
  529. UpdateTimeToNextInMemoryJob()
  530. /*++
  531. Must have called m_JobTimeLock.Lock();
  532. --*/
  533. {
  534. BOOL bSuccess = TRUE;
  535. SCHEDULEJOBMAP::iterator it;
  536. m_JobLock.Acquire(READER_LOCK);
  537. it = m_Jobs.begin();
  538. if(it != m_Jobs.end())
  539. {
  540. m_dwNextInMemoryJobTime = (*it).first;
  541. }
  542. else
  543. {
  544. m_dwNextInMemoryJobTime = WORKMANAGER_WAIT_FOREVER;
  545. }
  546. m_JobLock.Release(READER_LOCK);
  547. return bSuccess;
  548. }
  549. //-------------------------------------------------------------
  550. DWORD
  551. TranslateJobRunningAttributeToThreadPoolFlag(
  552. DWORD dwJobAttribute
  553. )
  554. /*++
  555. --*/
  556. {
  557. DWORD dwThreadPoolFlag = 0;
  558. if(dwJobAttribute & JOB_LONG_RUNNING)
  559. {
  560. dwThreadPoolFlag |= WT_EXECUTELONGFUNCTION;
  561. }
  562. else if(dwJobAttribute & JOB_INCLUDES_IO)
  563. {
  564. dwThreadPoolFlag |= WT_EXECUTEINIOTHREAD;
  565. }
  566. else
  567. {
  568. dwThreadPoolFlag = WT_EXECUTEDEFAULT; // = 0
  569. }
  570. return dwThreadPoolFlag;
  571. }
  572. public:
  573. //------------------------------------------------
  574. //
  575. // Constructor, only initialize member variable, must
  576. // invokd Init()
  577. //
  578. CWorkManager();
  579. //------------------------------------------------
  580. // Destructor.
  581. ~CWorkManager();
  582. //------------------------------------------------
  583. //
  584. // Startup Work Manager.
  585. //
  586. DWORD
  587. Startup(
  588. IN CWorkStorage* pPersistentWorkStorage,
  589. IN DWORD dwInterval = DEFAULT_WORK_INTERVAL,
  590. IN DWORD dwMaxConcurrentJob=DEFAULT_NUM_CONCURRENTJOB
  591. );
  592. //------------------------------------------------
  593. //
  594. // Schedule a Job
  595. //
  596. DWORD
  597. ScheduleJob(
  598. IN DWORD dwTime, // relative to current time.
  599. IN CWorkObject* pJob
  600. );
  601. //------------------------------------------------
  602. //
  603. // Shutdown WorkManager
  604. //
  605. void
  606. Shutdown();
  607. //------------------------------------------------
  608. //
  609. //
  610. inline DWORD
  611. GetNumberJobInMemoryQueue() {
  612. DWORD dwNumJob = 0;
  613. m_JobLock.Acquire(READER_LOCK);
  614. dwNumJob = m_Jobs.size();
  615. m_JobLock.Release(READER_LOCK);
  616. return dwNumJob;
  617. }
  618. //-------------------------------------------------------------
  619. inline DWORD
  620. GetNumberJobInStorageQueue() {
  621. return m_pPersistentWorkStorage->GetNumJobs();
  622. }
  623. //-------------------------------------------------------------
  624. DWORD
  625. GetNumberJobInProcessing()
  626. {
  627. DWORD dwNumJobs;
  628. m_InProcessingListLock.Lock();
  629. dwNumJobs = m_InProcessingList.size();
  630. m_InProcessingListLock.UnLock();
  631. return dwNumJobs;
  632. }
  633. //-------------------------------------------------------------
  634. DWORD
  635. GetTotalNumberJobInQueue()
  636. {
  637. return GetNumberJobInMemoryQueue() + GetNumberJobInStorageQueue();
  638. }
  639. //-------------------------------------------------------------
  640. #ifdef DBG
  641. void
  642. SuspendWorkManagerThread() {
  643. SuspendThread(m_hWorkMgrThread);
  644. };
  645. void
  646. ResumeWorkManagerThread() {
  647. ResumeThread(m_hWorkMgrThread);
  648. };
  649. #endif
  650. };
  651. //-------------------------------------------------------------
  652. class CWorkObject {
  653. friend class CWorkManager;
  654. private:
  655. CWorkManager* m_pWkMgr;
  656. long m_refCount; // reference counter
  657. DWORD m_dwLastRunStatus; // status from last Execute().
  658. BOOL m_bCanBeFree; // TRUE if work manager should call
  659. // SelfDestruct().
  660. DWORD m_dwScheduledTime; // time schedule to be processed by
  661. // work manager
  662. //
  663. // Private function invoke only by CWorkManager
  664. //
  665. long
  666. GetReferenceCount();
  667. void
  668. IncrementRefCount();
  669. void
  670. DecrementRefCount();
  671. void
  672. ExecuteWorkObject();
  673. void
  674. EndExecuteWorkObject();
  675. //------------------------------------------------------------
  676. //
  677. virtual void
  678. SetScheduledTime(
  679. IN DWORD dwTime
  680. )
  681. /*++
  682. Abstract:
  683. Set original scheduled processing time, this is call by work manager
  684. Parameter:
  685. dwTime : absolute scheduled time in second
  686. Returns:
  687. None.
  688. --*/
  689. {
  690. m_dwScheduledTime = dwTime;
  691. return;
  692. }
  693. protected:
  694. CWorkManager*
  695. GetWorkManager() {
  696. return m_pWkMgr;
  697. }
  698. BOOL
  699. CanBeDelete() {
  700. return m_bCanBeFree;
  701. }
  702. public:
  703. //------------------------------------------------------------
  704. //
  705. // Constructor
  706. //
  707. CWorkObject(
  708. IN BOOL bDestructorDelete = TRUE
  709. );
  710. //------------------------------------------------------------
  711. //
  712. // Destructor
  713. //
  714. ~CWorkObject()
  715. {
  716. Cleanup();
  717. }
  718. //------------------------------------------------------------
  719. //
  720. BOOL
  721. IsWorkManagerShuttingDown()
  722. {
  723. return (m_pWkMgr != NULL) ? m_pWkMgr->IsShuttingDown() : TRUE;
  724. }
  725. //------------------------------------------------------------
  726. // TODO - quick fix, persistent storage can't assign this.
  727. void
  728. SetProcessingWorkManager(
  729. IN CWorkManager* pWkMgr
  730. )
  731. /*++
  732. --*/
  733. {
  734. m_pWkMgr = pWkMgr;
  735. }
  736. //------------------------------------------------------------
  737. //
  738. virtual DWORD
  739. GetJobRestartTime()
  740. /*
  741. Abstract:
  742. Return suggested re-start time after server has been
  743. shutdown/restart, this is used by work storage class only.
  744. Parameter:
  745. None.
  746. Returns:
  747. Time in second relative to current time.
  748. --*/
  749. {
  750. return INFINITE;
  751. }
  752. //------------------------------------------------------------
  753. //
  754. virtual DWORD
  755. GetScheduledTime()
  756. /*++
  757. Abstract:
  758. Get Job's scheduled time.
  759. Parameter:
  760. None:
  761. Returns:
  762. Absolute scheduled time in seconds.
  763. --*/
  764. {
  765. return m_dwScheduledTime;
  766. }
  767. //------------------------------------------------------------
  768. //
  769. // Abstract:
  770. //
  771. // Initialize work object, similar to constructor.
  772. //
  773. virtual DWORD
  774. Init(
  775. IN BOOL bDestructorDelete = TRUE
  776. );
  777. //------------------------------------------------------------
  778. //
  779. virtual BOOL
  780. IsWorkPersistent()
  781. /*++
  782. Abstract:
  783. Return if this is persistent job - across session.
  784. Parameter:
  785. None.
  786. Returns:
  787. TRUE/FALSE.
  788. --*/
  789. {
  790. return FALSE;
  791. }
  792. //------------------------------------------------------------
  793. //
  794. virtual BOOL
  795. IsValid()
  796. /*++
  797. Abstract:
  798. Return if this object has been properly initialized.
  799. Parameter:
  800. None:
  801. Returns:
  802. TRUE/FALSE
  803. --*/
  804. {
  805. return m_pWkMgr != NULL;
  806. }
  807. //------------------------------------------------------------
  808. //
  809. virtual void
  810. Cleanup()
  811. /*++
  812. Abstract:
  813. Cleanup internal data in this object.
  814. Parameter:
  815. None.
  816. Returns:
  817. None.
  818. --*/
  819. {
  820. InterlockedExchange(&m_refCount, 0);
  821. return;
  822. }
  823. //------------------------------------------------------------
  824. //
  825. // Abstract:
  826. //
  827. // Pure virtual function to return type of work
  828. //
  829. // Parameter:
  830. //
  831. // None.
  832. //
  833. // Returns:
  834. //
  835. // Derived class dependent.
  836. //
  837. virtual DWORD
  838. GetWorkType() = 0;
  839. //------------------------------------------------------------
  840. //
  841. virtual BOOL
  842. SetWorkType(
  843. IN DWORD dwType
  844. )
  845. /*++
  846. Abstract:
  847. Set the type of work for this object, not call by any of work
  848. manager function.
  849. Parameter:
  850. dwType : Type of work.
  851. return:
  852. TRUE/FALSE.
  853. --*/
  854. {
  855. SetLastError(ERROR_INVALID_DATA);
  856. return FALSE;
  857. }
  858. //-----------------------------------------------------------
  859. //
  860. // Abstract:
  861. //
  862. // pure virtual function to return work object specific data.
  863. //
  864. // Parameters:
  865. //
  866. // ppbData : Pointer to pointer to buffer to receive object
  867. // specific work data.
  868. // pcbData : Pointer to DWORD to receive size of object specific
  869. // work data.
  870. //
  871. // Returns:
  872. //
  873. // TRUE/FALSE, all derived class specific.
  874. virtual BOOL
  875. GetWorkObjectData(
  876. OUT PBYTE* ppbData,
  877. OUT PDWORD pcbData
  878. ) = 0;
  879. //-----------------------------------------------------------
  880. //
  881. // Abstract:
  882. //
  883. // Pure virtual function for work storage class to assign
  884. // storage ID.
  885. //
  886. // Parameters:
  887. //
  888. // pbData : Work Storage assigned storage ID.
  889. // cbData : size of storage ID.
  890. //
  891. // Returns:
  892. //
  893. // TRUE/FALSE, derived class specific.
  894. //
  895. virtual BOOL
  896. SetJobId(
  897. IN PBYTE pbData,
  898. IN DWORD cbData
  899. ) = 0;
  900. //-----------------------------------------------------------
  901. //
  902. // Abstract:
  903. //
  904. // Pure virtual function to return storage ID assigned by
  905. // storage class.
  906. //
  907. // parameter:
  908. //
  909. // ppbData : Pointer to pointer to buffer to receive storage ID.
  910. // pcbData : size of storage ID.
  911. //
  912. // Returns:
  913. //
  914. // TRUE/FALSE, derived class specific.
  915. //
  916. virtual BOOL
  917. GetJobId(
  918. OUT PBYTE* ppbData,
  919. OUT PDWORD pcbData
  920. ) = 0;
  921. //-------------------------------------------------------------
  922. //
  923. // Abstract:
  924. //
  925. // Virtual function, execute a job.
  926. //
  927. // Parameters:
  928. //
  929. // None.
  930. //
  931. // Returns:
  932. //
  933. // None
  934. //
  935. virtual DWORD
  936. Execute() = 0;
  937. //-------------------------------------------------------------
  938. //
  939. // Abstract :
  940. //
  941. // Schedule a job at relative time
  942. //
  943. // Parameters:
  944. //
  945. // pftStartTime : Time relative to current system time, if NULL,
  946. // Job will be placed infront of job queue
  947. //
  948. // Return:
  949. //
  950. // TRUE if successful, FALSE otherwise
  951. //
  952. // Note:
  953. //
  954. // Could cause job stavation if set to NULL
  955. //
  956. virtual DWORD
  957. ScheduleJob(
  958. IN DWORD StartTime
  959. )
  960. /*++
  961. --*/
  962. {
  963. TLSASSERT(m_pWkMgr != NULL);
  964. return (m_pWkMgr == NULL) ? ERROR_INVALID_DATA : m_pWkMgr->ScheduleJob(StartTime, this);
  965. }
  966. //----------------------------------------------------------
  967. //
  968. // For threadpool function, see thread pool doc.
  969. //
  970. virtual DWORD
  971. GetJobRunningAttribute()
  972. {
  973. return JOB_INCLUDES_IO | JOB_LONG_RUNNING;
  974. }
  975. //---------------------------------------------------------------
  976. //
  977. // Return suggested schedule time relative to current time
  978. //
  979. virtual DWORD
  980. GetSuggestedScheduledTime() = 0;
  981. //--------------------------------------------------------------
  982. //
  983. // Get last status return from Execute().
  984. //
  985. virtual BOOL
  986. GetLastRunStatus() {
  987. return m_dwLastRunStatus;
  988. }
  989. //--------------------------------------------------------------
  990. //
  991. // Return TRUE if job can be deleted from queue
  992. //
  993. virtual BOOL
  994. IsJobCompleted() = 0;
  995. //-------------------------------------------------------------
  996. //
  997. // End Job, work manager, after invoke Execute(), calls EndJob()
  998. // to inform. work object that job has completed, derived class
  999. // should perform internal data cleanup.
  1000. //
  1001. virtual void
  1002. EndJob() = 0;
  1003. //-------------------------------------------------------------
  1004. //
  1005. // Pure virtual function, work manager operates on CWorkObject
  1006. // so it has no idea the actual class it is running, derive class
  1007. // should cast the pointer back to its class and delete the pointer
  1008. // to free up memory associated with object.
  1009. //
  1010. virtual BOOL
  1011. SelfDestruct() = 0;
  1012. //-------------------------------------------------------------
  1013. //
  1014. // Pure virtual, for debugging purpose only.
  1015. //
  1016. virtual LPCTSTR
  1017. GetJobDescription() = 0;
  1018. //--------------------------------------------------------
  1019. virtual void
  1020. SetJobRetryTimes(
  1021. IN DWORD dwRetries
  1022. ) = 0;
  1023. //--------------------------------------------------------
  1024. virtual DWORD
  1025. GetJobRetryTimes() = 0;
  1026. //---------------------------------------------------------
  1027. virtual void
  1028. SetJobInterval(
  1029. IN DWORD dwInterval
  1030. ) = 0;
  1031. //---------------------------------------------------------
  1032. virtual DWORD
  1033. GetJobInterval() = 0;
  1034. //---------------------------------------------------------
  1035. virtual void
  1036. SetJobRestartTime(
  1037. IN DWORD dwRestartTime
  1038. )
  1039. /*++
  1040. --*/
  1041. {
  1042. return;
  1043. }
  1044. };
  1045. #ifndef __TEST_WORKMGR__
  1046. #define TLSDebugOutput
  1047. #endif
  1048. //-----------------------------------------------------
  1049. #ifdef __cplusplus
  1050. extern "C" {
  1051. #endif
  1052. #ifdef __cplusplus
  1053. }
  1054. #endif
  1055. #endif