Leaked source code of windows server 2003
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.

2136 lines
58 KiB

  1. /*++
  2. 1998 Seagate Software, Inc. All rights reserved.
  3. Module Name:
  4. hsmjob.cpp
  5. Abstract:
  6. This class contains represents a job that can be performed by the HSM
  7. system.
  8. Author:
  9. Chuck Bardeen [cbardeen] 29-Oct-1996
  10. Revision History:
  11. --*/
  12. #include "stdafx.h"
  13. #include "wsb.h"
  14. #include "fsa.h"
  15. #include "job.h"
  16. #include "task.h"
  17. #include "engine.h"
  18. #include "HsmConn.h"
  19. #include "hsmjob.h"
  20. #define JOB_PARAMETER_MAX_ACTIVE_JOB OLESTR("MaximumNumberOfActiveJobs")
  21. #define MAX_ACTIVE_JOBS_DEFAULT 10
  22. #define WSB_TRACE_IS WSB_TRACE_BIT_JOB
  23. static USHORT iCountJob = 0; // Count of existing objects
  24. HRESULT
  25. CHsmJob::AdviseOfSessionState(
  26. IN IHsmSession* pSession,
  27. IN IHsmPhase* pPhase,
  28. IN OLECHAR* currentPath
  29. )
  30. /*++
  31. Implements:
  32. IHsmJobPriv::AdviseOfSessionState().
  33. --*/
  34. {
  35. HRESULT hr = S_OK;
  36. CONNECTDATA pConnectData;
  37. CComPtr<IConnectionPoint> pCP;
  38. CComPtr<IConnectionPointContainer> pCPC;
  39. CComPtr<IEnumConnections> pConnection;
  40. CComPtr<IHsmJobSinkEverySession> pSink;
  41. try {
  42. WsbAssert(0 != pSession, E_UNEXPECTED);
  43. // Tell everyone the new state of the session.
  44. WsbAffirmHr(((IUnknown*)(IHsmJob*) this)->QueryInterface(IID_IConnectionPointContainer, (void**) &pCPC));
  45. WsbAffirmHr(pCPC->FindConnectionPoint(IID_IHsmJobSinkEverySession, &pCP));
  46. WsbAffirmHr(pCP->EnumConnections(&pConnection));
  47. while(pConnection->Next(1, &pConnectData, 0) == S_OK) {
  48. // We don't care if the sink has problems (it's their problem).
  49. try {
  50. WsbAffirmHr((pConnectData.pUnk)->QueryInterface(IID_IHsmJobSinkEverySession, (void**) &pSink));
  51. WsbAffirmHr(pSink->ProcessJobSession(pSession, pPhase, currentPath));
  52. } WsbCatchAndDo(hr, hr = S_OK;);
  53. WsbAffirmHr((pConnectData.pUnk)->Release());
  54. pSink=0;
  55. }
  56. } WsbCatch(hr);
  57. return(hr);
  58. }
  59. HRESULT
  60. CHsmJob::Cancel(
  61. IN HSM_JOB_PHASE phase
  62. )
  63. /*++
  64. Implements:
  65. IHsmJob::Cancel().
  66. --*/
  67. {
  68. HRESULT hr = S_OK;
  69. HRESULT hr2;
  70. CComPtr<IHsmJobWorkItemPriv> pWorkItem;
  71. CComPtr<IHsmSession> pSession;
  72. CComPtr<IWsbEnum> pEnum;
  73. WsbTraceIn(OLESTR("CHsmJob::Cancel"), OLESTR("Phase = <%d>"), phase);
  74. try {
  75. m_state = HSM_JOB_STATE_CANCELLING;
  76. WsbLogEvent(JOB_MESSAGE_JOB_CANCELLING, 0, NULL, (OLECHAR*) m_name, NULL);
  77. WsbAffirmHr(EnumWorkItems(&pEnum));
  78. // Tell all the session we have to cancel the phase(s).
  79. for (hr = pEnum->First(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem);
  80. (hr == S_OK);
  81. hr = pEnum->Next(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem)) {
  82. WsbAffirmHr(pWorkItem->GetSession(&pSession));
  83. if (pSession != 0) {
  84. WsbAffirmHr(pSession->Cancel(phase));
  85. // If we are quiting the entire job, we need to cleanup in case
  86. // the session refuses to terminate properly (i.e. one of the
  87. // subordinates to the session is out to lunch).
  88. if (phase == HSM_JOB_PHASE_ALL) {
  89. WsbTrace(OLESTR("CHsmJob::Cancel - Cancelling all.\n"));
  90. m_isTerminating = TRUE;
  91. // Fake the work item into thinking that the session completed, since we
  92. // don't want to rely upon it completing normally
  93. try {
  94. CComPtr<IHsmPhase> pPhase;
  95. CComPtr<IHsmPhasePriv> pPhasePriv;
  96. CComPtr<IHsmSessionSinkEveryState> pSink;
  97. WsbAffirmHr(CoCreateInstance(CLSID_CHsmPhase, 0, CLSCTX_ALL, IID_IHsmPhasePriv, (void**) &pPhasePriv));
  98. WsbAffirmHr(pPhasePriv->SetPhase(HSM_JOB_PHASE_ALL));
  99. WsbAffirmHr(pPhasePriv->SetState(HSM_JOB_STATE_CANCELLED));
  100. WsbAffirmHr(pPhasePriv->QueryInterface(IID_IHsmPhase, (void**) &pPhase));
  101. WsbAffirmHr(pWorkItem->QueryInterface(IID_IHsmSessionSinkEveryState, (void**) &pSink));
  102. WsbAffirmHr(pSink->ProcessSessionState(pSession, pPhase, OLESTR("")));
  103. } WsbCatchAndDo(hr2, pSession->ProcessHr(phase, __FILE__, __LINE__, hr2););
  104. }
  105. pSession = 0;
  106. }
  107. pWorkItem = 0;
  108. }
  109. if (hr == WSB_E_NOTFOUND) {
  110. hr = S_OK;
  111. }
  112. m_state = HSM_JOB_STATE_CANCELLED;
  113. } WsbCatch(hr);
  114. WsbTraceOut(OLESTR("CHsmJob::Cancel"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  115. return(hr);
  116. }
  117. HRESULT
  118. CHsmJob::CheckResourceNotInUse(
  119. IN GUID resid
  120. )
  121. /*++
  122. Routine Description:
  123. Determines if another job is using this resource or if too many jobs
  124. are already active.
  125. Arguments:
  126. resid - Id of the resource in question.
  127. Return Value:
  128. S_OK - Resource is not in use.
  129. S_FALSE - Resource is in use.
  130. E_* - An error occurred.
  131. --*/
  132. {
  133. HRESULT hr = S_OK;
  134. WsbTraceIn(OLESTR("CHsmJob::CheckResourceNotInUse"),
  135. OLESTR("resource id = <%ls>"), WsbGuidAsString(resid));
  136. try {
  137. ULONG nJobs;
  138. ULONG nJobsActive = 0;
  139. CComPtr<IHsmServer> pHsmServer;
  140. CComPtr<IWsbIndexedCollection> pJobs;
  141. // Get list of jobs
  142. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, m_hsmId, IID_IHsmServer, (void**) &pHsmServer));
  143. WsbAffirmHr(pHsmServer->GetJobs(&pJobs));
  144. // Loop over jobs
  145. WsbAffirmHr(pJobs->GetEntries(&nJobs));
  146. for (ULONG i = 0; i < nJobs; i++) {
  147. CWsbStringPtr JobName;
  148. GUID l_guid;
  149. CComPtr<IHsmJob> pJob;
  150. CComPtr<IHsmJobWorkItemPriv> pWorkItem;
  151. CComPtr<IWsbEnum> pEnum;
  152. HRESULT hrEnum;
  153. HSM_JOB_STATE state;
  154. pJob = 0;
  155. WsbAffirmHr(pJobs->At(i, IID_IHsmJob, (void**) &pJob));
  156. // Ignore this job if it's not active
  157. if (S_OK == pJob->GetName(&JobName, 0)) {
  158. WsbTrace(OLESTR("CHsmJob::CheckResourceNotInUse: job <%ls>\n"),
  159. static_cast<OLECHAR*>(JobName));
  160. JobName.Free();
  161. }
  162. hr = pJob->IsActive();
  163. if (S_FALSE == hr) {
  164. hr = S_OK;
  165. continue;
  166. } else {
  167. WsbAffirmHr(hr);
  168. }
  169. // Ignore this job if it's suspended
  170. WsbAffirmHr(pJob->GetState(&state));
  171. if ((HSM_JOB_STATE_SUSPENDED == state) || (HSM_JOB_STATE_SUSPENDING == state)) {
  172. continue;
  173. }
  174. nJobsActive++;
  175. // The job is active, check against all of its active work items
  176. WsbAffirmHr(pJob->EnumWorkItems(&pEnum));
  177. for (hrEnum = pEnum->First(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem);
  178. (hrEnum == S_OK);
  179. hrEnum = pEnum->Next(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem)) {
  180. hr = pWorkItem->IsActiveItem();
  181. if (S_FALSE == hr) {
  182. // work item is not active at all, skip it...
  183. hr = S_OK;
  184. pWorkItem = 0;
  185. continue;
  186. } else {
  187. WsbAffirmHr(hr);
  188. }
  189. // Get the resource (volume) id that the active work item is using
  190. // (or wants to use)
  191. WsbAffirmHr(pWorkItem->GetResourceId(&l_guid));
  192. WsbTrace(OLESTR("CHsmJob:: l_guid = <%ls>\n"), WsbGuidAsString(l_guid));
  193. if (l_guid == resid) {
  194. WsbTrace(OLESTR("CHsmJob::CheckResourceNotInUse: resource in use\n"));
  195. hr = S_FALSE;
  196. break;
  197. }
  198. pWorkItem = 0;
  199. }
  200. pEnum = 0;
  201. if (hr == S_FALSE) {
  202. // resource in use, no need to continue enumerating jobs
  203. break;
  204. }
  205. }
  206. // Limit the number of active jobs
  207. WsbTrace(OLESTR("CHsmJob::CheckResourceNotInUse: total jobs = %lu, active jobs = %lu\n"),
  208. nJobs, nJobsActive);
  209. DWORD size;
  210. OLECHAR tmpString[256];
  211. DWORD maxJobs = MAX_ACTIVE_JOBS_DEFAULT;
  212. if (SUCCEEDED(WsbGetRegistryValueString(NULL, HSM_ENGINE_REGISTRY_STRING, JOB_PARAMETER_MAX_ACTIVE_JOB, tmpString, 256, &size))) {
  213. maxJobs = wcstol(tmpString, NULL, 10);
  214. if (0 == maxJobs) {
  215. // Illegal value, get back to default
  216. maxJobs = MAX_ACTIVE_JOBS_DEFAULT;
  217. }
  218. }
  219. WsbTrace(OLESTR("CHsmJob::CheckResourceNotInUse: max active jobs = %lu\n"), maxJobs);
  220. if (nJobsActive >= maxJobs) {
  221. WsbTrace(OLESTR("CHsmJob::CheckResourceNotInUse: too many active jobs\n"),
  222. nJobsActive);
  223. hr = S_FALSE;
  224. }
  225. } WsbCatch(hr);
  226. WsbTraceOut(OLESTR("CHsmJob::CheckResourceNotInUse"), OLESTR("hr = <%ls>"),
  227. WsbHrAsString(hr));
  228. return(hr);
  229. }
  230. HRESULT
  231. CHsmJob::DidFinish(
  232. void
  233. )
  234. /*++
  235. Implements:
  236. IHsmJob::DidFinish().
  237. --*/
  238. {
  239. HRESULT hr = S_OK;
  240. CComPtr<IHsmJobWorkItem> pWorkItem;
  241. CComPtr<IWsbEnum> pEnum;
  242. HSM_JOB_STATE state;
  243. try {
  244. WsbAffirmHr(EnumWorkItems(&pEnum));
  245. // If any of the items aren't done then the work wasn't finished. This means
  246. // that we would want to try again on failed items.
  247. for (hr = pEnum->First(IID_IHsmJobWorkItem, (void**) &pWorkItem);
  248. (hr == S_OK);
  249. hr = pEnum->Next(IID_IHsmJobWorkItem, (void**) &pWorkItem)) {
  250. WsbAffirmHr(pWorkItem->GetState(&state));
  251. if ((HSM_JOB_STATE_DONE != state) && (HSM_JOB_STATE_SKIPPED != state) && (HSM_JOB_STATE_FAILED != state)) {
  252. hr = S_FALSE;
  253. }
  254. pWorkItem = 0;
  255. }
  256. if (hr == WSB_E_NOTFOUND) {
  257. hr = S_OK;
  258. }
  259. } WsbCatch(hr);
  260. return(hr);
  261. }
  262. HRESULT
  263. CHsmJob::DidFinishOk(
  264. void
  265. )
  266. /*++
  267. Implements:
  268. IHsmJob::DidFinishOk().
  269. --*/
  270. {
  271. HRESULT hr = S_OK;
  272. CComPtr<IHsmJobWorkItem> pWorkItem;
  273. CComPtr<IWsbEnum> pEnum;
  274. HSM_JOB_STATE state;
  275. try {
  276. WsbAffirmHr(EnumWorkItems(&pEnum));
  277. // If any of the items aren't done then the work wasn't finished. This means
  278. // that we would want to try again on failed items.
  279. for (hr = pEnum->First(IID_IHsmJobWorkItem, (void**) &pWorkItem);
  280. (hr == S_OK);
  281. hr = pEnum->Next(IID_IHsmJobWorkItem, (void**) &pWorkItem)) {
  282. WsbAffirmHr(pWorkItem->GetState(&state));
  283. if ((HSM_JOB_STATE_DONE != state) && (HSM_JOB_STATE_SKIPPED != state)) {
  284. hr = S_FALSE;
  285. }
  286. pWorkItem = 0;
  287. }
  288. if (hr == WSB_E_NOTFOUND) {
  289. hr = S_OK;
  290. }
  291. } WsbCatch(hr);
  292. return(hr);
  293. }
  294. HRESULT
  295. CHsmJob::Do(
  296. void
  297. )
  298. /*++
  299. --*/
  300. {
  301. HRESULT hr = S_OK;
  302. CComPtr<IConnectionPointContainer> pCPC;
  303. CComPtr<IConnectionPoint> pCP;
  304. CComPtr<IFsaResource> pResource;
  305. CComPtr<IHsmSession> pSession;
  306. CComPtr<IHsmSessionSinkEveryState> pSink;
  307. CComPtr<IHsmJobWorkItemPriv> pWorkItem;
  308. CComPtr<IHsmJobWorkItem> pWorkItemScan;
  309. CComPtr<IWsbEnum> pEnum;
  310. CComPtr<IHsmServer> pHsmServer;
  311. HSM_JOB_STATE state;
  312. GUID managingHsm;
  313. ULONG i = 0;
  314. FILETIME fileTime;
  315. CWsbStringPtr startingPath;
  316. DWORD cookie;
  317. ULONG maxActiveSessions;
  318. CWsbStringPtr resourceName;
  319. GUID ResourceId = GUID_NULL;
  320. WsbTraceIn(OLESTR("CHsmJob::Do"), OLESTR(""));
  321. try {
  322. WsbAssert(m_pContext != 0, E_UNEXPECTED);
  323. // Check if jobs are disabled
  324. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, m_hsmId, IID_IHsmServer, (void**) &pHsmServer));
  325. hr = pHsmServer->AreJobsEnabled();
  326. if (S_FALSE == hr) {
  327. // Jobs are disabled; suspend the job
  328. WsbAffirmHr(Suspend(HSM_JOB_PHASE_ALL));
  329. WsbThrow(hr);
  330. } else {
  331. WsbAffirmHr(hr);
  332. }
  333. // The job will enumerate over the work list.
  334. WsbAffirmHr(EnumWorkItems(&pEnum));
  335. // Go through the list of work items and start a session for anything that needs
  336. // work up to the limit of the number of sessions that can be active at one time.
  337. WsbAffirmHr(GetMaxActiveSessions(&maxActiveSessions));
  338. for (hr = pEnum->First(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem);
  339. SUCCEEDED(hr) && (m_activeSessions < maxActiveSessions);
  340. hr = pEnum->Next(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem)) {
  341. // If we should do this item, then find it's resource.
  342. WsbAffirmHr(pWorkItem->GetState(&state));
  343. // Only do work for items that are currently idle.
  344. if (HSM_JOB_STATE_IDLE == state) {
  345. // Check if the required resource is in use by another job
  346. WsbAffirmHr(pWorkItem->GetResourceId(&ResourceId));
  347. hr = CheckResourceNotInUse(ResourceId);
  348. if (S_FALSE == hr) {
  349. // Resource is not available; suspend the job
  350. WsbAffirmHr(Suspend(HSM_JOB_PHASE_ALL));
  351. break;
  352. } else {
  353. WsbAffirmHr(hr);
  354. }
  355. // Indicate that we are trying to start a session. This prevents us from trying
  356. // again.
  357. WsbAffirmHr(pWorkItem->SetState(HSM_JOB_STATE_STARTING));
  358. try {
  359. fileTime.dwHighDateTime = 0;
  360. fileTime.dwLowDateTime = 0;
  361. WsbAffirmHr(pWorkItem->SetFinishTime(fileTime));
  362. WsbAffirmHr(CoFileTimeNow(&fileTime));
  363. WsbAffirmHr(pWorkItem->SetStartTime(fileTime));
  364. WsbTrace(OLESTR("CHsmJob::Do, resource id = %ls\n"),
  365. WsbGuidAsString(ResourceId));
  366. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_RESOURCE,
  367. ResourceId, IID_IFsaResource, (void**) &pResource));
  368. //
  369. // Get the resource name for event logging
  370. try {
  371. WsbAffirmHr(pResource->GetName(&resourceName, 0));
  372. WsbTrace(OLESTR("CHsmJob::Do, resource name = <%ls>\n"), resourceName);
  373. } WsbCatch( hr );
  374. // We will only do jobs that come from the managing HSM.
  375. WsbAffirmHr(pResource->GetManagingHsm(&managingHsm));
  376. if (!IsEqualGUID(managingHsm, m_hsmId)) {
  377. WsbTrace(OLESTR("CHsmJob::Do, HSM of resource = %ls\n"),
  378. WsbGuidAsString(managingHsm));
  379. WsbTrace(OLESTR("CHsmJob::Do, HSM of job = %ls\n"),
  380. WsbGuidAsString(m_hsmId));
  381. hr = JOB_E_NOTMANAGINGHSM;
  382. WsbLogEvent(JOB_MESSAGE_JOB_FAILED_NOTMANAGINGHSM, 0, NULL, (OLECHAR*) m_name, (OLECHAR *)resourceName, WsbHrAsString(hr),NULL);
  383. WsbThrow(hr);
  384. }
  385. m_state = HSM_JOB_STATE_ACTIVE;
  386. // Set job item as active (started)
  387. WsbAffirmHr(pWorkItem->SetActiveItem(TRUE));
  388. // Do the pre-scan action if it exists
  389. WsbAffirmHr(pWorkItem->QueryInterface(IID_IHsmJobWorkItem,
  390. (void**)&pWorkItemScan));
  391. WsbAffirmHr(pWorkItemScan->DoPreScan());
  392. // Create a session (owned by the resource) that will do the scan of this
  393. // resource.
  394. i++;
  395. WsbAffirmHr(pResource->StartJobSession((IHsmJob*) this, i, &pSession));
  396. // Ask the session to advise of every state changes.
  397. WsbAffirmHr(pWorkItem->QueryInterface(IID_IHsmSessionSinkEveryState, (void**) &pSink));
  398. WsbAffirmHr(pSession->QueryInterface(IID_IConnectionPointContainer, (void**) &pCPC));
  399. WsbAffirmHr(pCPC->FindConnectionPoint(IID_IHsmSessionSinkEveryState, &pCP));
  400. WsbAffirmHr(pCP->Advise(pSink, &cookie));
  401. // Now start the scanner of the resource
  402. WsbAffirmHr(pWorkItem->GetStartingPath(&startingPath, 0));
  403. WsbAffirmHr(pResource->StartJob(startingPath, pSession));
  404. // Increment the count of active sessions.
  405. m_activeSessions++;
  406. // Update the information in the work list.
  407. WsbAffirmHr(pWorkItem->SetSession(pSession));
  408. WsbAffirmHr(pWorkItem->SetCookie(cookie));
  409. } WsbCatchAndDo(hr, pWorkItem->SetState(HSM_JOB_STATE_FAILED);
  410. WsbLogEvent(JOB_MESSAGE_JOB_FAILED, 0, NULL, (OLECHAR*) m_name, (OLECHAR *) resourceName, WsbHrAsString(hr), NULL);
  411. );
  412. pCP = 0;
  413. pCPC = 0;
  414. pSession = 0;
  415. pResource = 0;
  416. pSink = 0;
  417. }
  418. pWorkItem = 0;
  419. }
  420. if (hr == WSB_E_NOTFOUND) {
  421. hr = S_OK;
  422. // If we got to the end of the list and no session are active, then we are done.
  423. if (m_activeSessions == 0) {
  424. m_isActive = FALSE;
  425. m_state = HSM_JOB_STATE_IDLE;
  426. WsbLogEvent(JOB_MESSAGE_JOB_COMPLETED, 0, NULL, (OLECHAR*) m_name, NULL);
  427. }
  428. }
  429. } WsbCatch(hr);
  430. WsbTraceOut(OLESTR("CHsmJob::Do"), OLESTR("hr = <%ls>, isActive = <%ls>, activeSessions = <%lu>"),
  431. WsbHrAsString(hr), WsbBoolAsString(m_isActive), m_activeSessions);
  432. return(hr);
  433. }
  434. HRESULT
  435. CHsmJob::DoNext(
  436. void
  437. )
  438. /*++
  439. Implements:
  440. IHsmJobPriv::DoNext().
  441. --*/
  442. {
  443. HRESULT hr = S_OK;
  444. WsbTraceIn(OLESTR("CHsmJob::DoNext"), OLESTR("Active sessions = <%lu>, Terminating = <%ls>"),
  445. m_activeSessions, WsbBoolAsString(m_isTerminating));
  446. try {
  447. // Decrement the count of active sessions.
  448. if (m_activeSessions > 0) {
  449. m_activeSessions--;
  450. // If we are not terminating look for more work
  451. if (FALSE == m_isTerminating) {
  452. // See if there is anthing else to do.
  453. WsbAffirmHr(Do());
  454. } else {
  455. m_isActive = FALSE;
  456. m_state = HSM_JOB_STATE_IDLE;
  457. }
  458. } else {
  459. m_isActive = FALSE;
  460. m_state = HSM_JOB_STATE_IDLE;
  461. }
  462. // If we are done with the work, make sure we
  463. // clear the terminating flag
  464. if (0 == m_activeSessions) {
  465. m_isTerminating = FALSE;
  466. }
  467. // Restart other jobs that may be suspended
  468. WsbAffirmHr(RestartSuspendedJobs());
  469. } WsbCatch(hr);
  470. WsbTraceOut(OLESTR("CHsmJob::DoNext"), OLESTR("hr = <%ls>, isActive = <%ls>, activeSessions = <%lu>"),
  471. WsbHrAsString(hr), WsbBoolAsString(m_isActive), m_activeSessions);
  472. return(hr);
  473. }
  474. HRESULT
  475. CHsmJob::EnumWorkItems(
  476. IN IWsbEnum** ppEnum
  477. )
  478. /*++
  479. Implements:
  480. IHsmJob::EnumWorkItems().
  481. --*/
  482. {
  483. HRESULT hr = S_OK;
  484. try {
  485. WsbAssert(0 != ppEnum, E_POINTER);
  486. WsbAffirmHr(m_pWorkItems->Enum(ppEnum));
  487. } WsbCatch(hr);
  488. return(hr);
  489. }
  490. HRESULT
  491. CHsmJob::FinalConstruct(
  492. void
  493. )
  494. /*++
  495. Implements:
  496. CComObjectRoot::FinalConstruct().
  497. --*/
  498. {
  499. HRESULT hr = S_OK;
  500. WsbTraceIn(OLESTR("CHsmJob::FinalConstruct"),OLESTR(""));
  501. try {
  502. WsbAffirmHr(CWsbObject::FinalConstruct());
  503. m_state = HSM_JOB_STATE_IDLE;
  504. m_hsmId = GUID_NULL;
  505. m_isUserDefined = FALSE;
  506. m_activeSessions = 0;
  507. m_runId = 0;
  508. m_isActive = FALSE;
  509. m_isTerminating = FALSE;
  510. // Each instance should have its own unique identifier.
  511. WsbAffirmHr(CoCreateGuid(&m_id));
  512. // Create the work list collection.
  513. WsbAffirmHr(CoCreateInstance(CLSID_CWsbOrderedCollection, 0, CLSCTX_ALL, IID_IWsbCollection, (void**) &m_pWorkItems));
  514. } WsbCatch(hr);
  515. iCountJob++;
  516. WsbTraceOut(OLESTR("CHsmJob::FinalConstruct"), OLESTR("Count is <%d>"), iCountJob);
  517. return(hr);
  518. }
  519. void
  520. CHsmJob::FinalRelease(
  521. void
  522. )
  523. /*++
  524. Implements:
  525. CComObjectRoot::FinalRelease().
  526. --*/
  527. {
  528. WsbTraceIn(OLESTR("CHsmJob::FinalRelease"),OLESTR(""));
  529. // Let the parent class do his thing.
  530. CWsbObject::FinalRelease();
  531. iCountJob--;
  532. WsbTraceOut(OLESTR("CHsmJob::FinalRelease"), OLESTR("Count is <%d>"), iCountJob);
  533. }
  534. HRESULT
  535. CHsmJob::FindWorkItem(
  536. IN IHsmSession* pSession,
  537. OUT IHsmJobWorkItem** ppWorkItem
  538. )
  539. /*++
  540. Implements:
  541. IHsmJob::FindWorkItem().
  542. --*/
  543. {
  544. HRESULT hr = S_OK;
  545. CComPtr<IHsmSession> pItemSession;
  546. CComPtr<IHsmJobWorkItem> pWorkItem;
  547. CComPtr<IWsbEnum> pEnum;
  548. GUID id;
  549. GUID id2;
  550. try {
  551. WsbAssert(0 != ppWorkItem, E_POINTER);
  552. // The job will enumerate over the work list.
  553. WsbAffirmHr(EnumWorkItems(&pEnum));
  554. // Go through the list of work items and see if we have one with this session interface.
  555. *ppWorkItem = 0;
  556. WsbAffirmHr(pSession->GetIdentifier(&id));
  557. hr = pEnum->First(IID_IHsmJobWorkItem, (void**) &pWorkItem);
  558. while (SUCCEEDED(hr) && (*ppWorkItem == 0)) {
  559. // NOTE: Pointer comparisson is probably not going to work, since DCOM may change
  560. // the value of the pointer. We could cache the sessionId in the workItem to
  561. // make the loop a little faster, but it doesn't seem like a big performance issue.
  562. WsbAffirmHr(pWorkItem->GetSession(&pItemSession));
  563. if (pItemSession != 0) {
  564. WsbAffirmHr(pItemSession->GetIdentifier(&id2));
  565. if (memcmp(&id, &id2, sizeof(GUID)) == 0) {
  566. *ppWorkItem = pWorkItem;
  567. pWorkItem.p->AddRef();
  568. } else {
  569. pWorkItem = 0;
  570. pItemSession = 0;
  571. hr = pEnum->Next(IID_IHsmJobWorkItem, (void**) &pWorkItem);
  572. }
  573. }
  574. }
  575. } WsbCatch(hr);
  576. return(hr);
  577. }
  578. HRESULT
  579. CHsmJob::GetClassID(
  580. OUT CLSID* pClsid
  581. )
  582. /*++
  583. Implements:
  584. IPersist::GetClassID().
  585. --*/
  586. {
  587. HRESULT hr = S_OK;
  588. WsbTraceIn(OLESTR("CHsmJob::GetClassID"), OLESTR(""));
  589. try {
  590. WsbAssert(0 != pClsid, E_POINTER);
  591. *pClsid = CLSID_CHsmJob;
  592. } WsbCatch(hr);
  593. WsbTraceOut(OLESTR("CHsmJob::GetClassID"), OLESTR("hr = <%ls>, CLSID = <%ls>"), WsbHrAsString(hr), WsbGuidAsString(*pClsid));
  594. return(hr);
  595. }
  596. HRESULT
  597. CHsmJob::GetContext(
  598. OUT IHsmJobContext** ppContext
  599. )
  600. /*++
  601. Implements:
  602. IHsmJob::GetContext().
  603. --*/
  604. {
  605. HRESULT hr = S_OK;
  606. try {
  607. WsbAssert(0 != ppContext, E_POINTER);
  608. *ppContext = m_pContext;
  609. if (m_pContext != 0) {
  610. m_pContext.p->AddRef();
  611. }
  612. } WsbCatch(hr);
  613. return(hr);
  614. }
  615. HRESULT
  616. CHsmJob::GetDef(
  617. OUT IHsmJobDef** ppDef
  618. )
  619. /*++
  620. Implements:
  621. IHsmJob::GetDef().
  622. --*/
  623. {
  624. HRESULT hr = S_OK;
  625. try {
  626. WsbAssert(0 != ppDef, E_POINTER);
  627. *ppDef = m_pDef;
  628. if (m_pDef != 0) {
  629. m_pDef.p->AddRef();
  630. }
  631. } WsbCatch(hr);
  632. return(hr);
  633. }
  634. HRESULT
  635. CHsmJob::GetIdentifier(
  636. OUT GUID* pId
  637. )
  638. /*++
  639. Implements:
  640. IHsmJob::GetIdentifier().
  641. --*/
  642. {
  643. HRESULT hr = S_OK;
  644. try {
  645. WsbAssert(0 != pId, E_POINTER);
  646. *pId = m_id;
  647. } WsbCatch(hr);
  648. return(hr);
  649. }
  650. HRESULT
  651. CHsmJob::GetHsmId(
  652. OUT GUID* pId
  653. )
  654. /*++
  655. Implements:
  656. IHsmJob::GetHsmId().
  657. --*/
  658. {
  659. HRESULT hr = S_OK;
  660. try {
  661. WsbAssert(0 != pId, E_POINTER);
  662. *pId = m_hsmId;
  663. } WsbCatch(hr);
  664. return(hr);
  665. }
  666. HRESULT
  667. CHsmJob::GetMaxActiveSessions(
  668. OUT ULONG* pMaxActiveSessions
  669. )
  670. /*++
  671. Implements:
  672. IHsmJob::GetMaxActiveSessions().
  673. --*/
  674. {
  675. HRESULT hr = S_OK;
  676. try {
  677. CComPtr<IHsmServer> pHsmServer;
  678. WsbAssert(0 != pMaxActiveSessions, E_POINTER);
  679. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, m_hsmId, IID_IHsmServer, (void**) &pHsmServer));
  680. // Currently, the only job with more than one item is the default Copy Files job.
  681. // Therefore, the limit is set according to the Copy Files limit
  682. WsbAffirmHr(pHsmServer->GetCopyFilesLimit(pMaxActiveSessions));
  683. } WsbCatch(hr);
  684. return(hr);
  685. }
  686. HRESULT
  687. CHsmJob::GetName(
  688. OUT OLECHAR** pName,
  689. IN ULONG bufferSize
  690. )
  691. /*++
  692. Implements:
  693. IHsmJob::GetName().
  694. --*/
  695. {
  696. HRESULT hr = S_OK;
  697. try {
  698. WsbAssert(0 != pName, E_POINTER);
  699. WsbAffirmHr(m_name.CopyTo(pName, bufferSize));
  700. } WsbCatch(hr);
  701. return(hr);
  702. }
  703. HRESULT
  704. CHsmJob::GetRunId(
  705. OUT ULONG* pRunId
  706. )
  707. /*++
  708. Implements:
  709. IHsmJob::GetRunId().
  710. --*/
  711. {
  712. HRESULT hr = S_OK;
  713. try {
  714. WsbAssert(0 != pRunId, E_POINTER);
  715. *pRunId = m_runId;
  716. } WsbCatch(hr);
  717. return(hr);
  718. }
  719. HRESULT
  720. CHsmJob::GetSizeMax(
  721. OUT ULARGE_INTEGER* pSize
  722. )
  723. /*++
  724. Implements:
  725. IPersistStream::GetSizeMax().
  726. --*/
  727. {
  728. HRESULT hr = S_OK;
  729. CComPtr<IPersistStream> pPersistStream;
  730. ULARGE_INTEGER entrySize;
  731. WsbTraceIn(OLESTR("CHsmJob::GetSizeMax"), OLESTR(""));
  732. try {
  733. pSize->QuadPart = 2 * WsbPersistSizeOf(GUID) + 3 * WsbPersistSizeOf(BOOL) + 2 * WsbPersistSizeOf(ULONG) + WsbPersistSize((wcslen(m_name) + 1) * sizeof(OLECHAR));
  734. if (m_pContext != 0) {
  735. WsbAffirmHr(m_pContext->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  736. WsbAffirmHr(pPersistStream->GetSizeMax(&entrySize));
  737. pPersistStream = 0;
  738. pSize->QuadPart += entrySize.QuadPart;
  739. }
  740. if (m_pDef != 0) {
  741. WsbAffirmHr(m_pDef->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  742. WsbAffirmHr(pPersistStream->GetSizeMax(&entrySize));
  743. pPersistStream = 0;
  744. pSize->QuadPart += entrySize.QuadPart;
  745. }
  746. WsbAffirmHr(m_pWorkItems->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  747. WsbAffirmHr(pPersistStream->GetSizeMax(&entrySize));
  748. pPersistStream = 0;
  749. pSize->QuadPart += entrySize.QuadPart;
  750. } WsbCatch(hr);
  751. WsbTraceOut(OLESTR("CHsmJob::GetSizeMax"), OLESTR("hr = <%ls>, Size = <%ls>"), WsbHrAsString(hr), WsbPtrToUliAsString(pSize));
  752. return(hr);
  753. }
  754. HRESULT
  755. CHsmJob::GetState(
  756. OUT HSM_JOB_STATE* pState
  757. )
  758. /*++
  759. Implements:
  760. IHsmJob::GetState().
  761. --*/
  762. {
  763. HRESULT hr = S_OK;
  764. try {
  765. WsbAssert(0 != pState, E_POINTER);
  766. *pState = m_state;
  767. } WsbCatch(hr);
  768. return(hr);
  769. }
  770. HRESULT
  771. CHsmJob::InitAs(
  772. IN OLECHAR* name,
  773. IN IHsmJobDef* pDef,
  774. IN HSM_JOB_DEF_TYPE type,
  775. IN GUID storagePool,
  776. IN IHsmServer* pServer,
  777. IN BOOL isUserDefined,
  778. IN IFsaResource* pResource
  779. )
  780. /*++
  781. Implements:
  782. IHsmJob::InitAs().
  783. --*/
  784. {
  785. HRESULT hr = S_OK;
  786. GUID id;
  787. GUID hsmId;
  788. CComPtr<IHsmJobContext> pContext;
  789. CComPtr<IWsbGuid> pGuid;
  790. CComPtr<IWsbCollection> pCollection;
  791. CComPtr<IWsbCreateLocalObject> pCreateObj;
  792. try {
  793. WsbAssert(0 != pServer, E_POINTER);
  794. WsbAssert(0 != name, E_POINTER);
  795. // All objects created need to be owned by the engine, and also get some
  796. // information about the engine.
  797. WsbAssertHr(pServer->QueryInterface(IID_IWsbCreateLocalObject, (void**) &pCreateObj));
  798. WsbAssertHr(pServer->GetID(&hsmId));
  799. // If a definition was provided we use that one; otherwise, a new one is created.
  800. if (0 != pDef) {
  801. m_pDef = pDef;
  802. } else {
  803. m_pDef = 0;
  804. WsbAssertHr(pCreateObj->CreateInstance(CLSID_CHsmJobDef, IID_IHsmJobDef, (void**) &m_pDef));
  805. WsbAffirmHr(m_pDef->InitAs(name, type, storagePool, pServer, isUserDefined));
  806. }
  807. // Create a job context, fill it out, and then add it to the job.
  808. WsbAssertHr(pCreateObj->CreateInstance(CLSID_CHsmJobContext, IID_IHsmJobContext, (void**) &pContext));
  809. // If a specific resource is target, then set up the context appropriately.
  810. if (0 != pResource) {
  811. WsbAssertHr(pContext->SetUsesAllManaged(FALSE));
  812. WsbAssertHr(pCreateObj->CreateInstance(CLSID_CWsbGuid, IID_IWsbGuid, (void**) &pGuid));
  813. WsbAssertHr(pContext->Resources(&pCollection));
  814. WsbAssertHr(pResource->GetIdentifier(&id));
  815. WsbAssertHr(pGuid->SetGuid(id));
  816. WsbAssertHr(pCollection->Add(pGuid));
  817. } else {
  818. WsbAssertHr(pContext->SetUsesAllManaged(TRUE));
  819. }
  820. m_pContext = pContext;
  821. // There are a couple of other fields to fill out in the job.
  822. m_hsmId = hsmId;
  823. m_isUserDefined = isUserDefined;
  824. m_name = name;
  825. } WsbCatch(hr);
  826. return(hr);
  827. }
  828. HRESULT
  829. CHsmJob::IsActive(
  830. void
  831. )
  832. /*++
  833. Implements:
  834. IHsmJob::IsActive().
  835. --*/
  836. {
  837. HRESULT hr = S_OK;
  838. WsbTraceIn(OLESTR("CHsmJob::IsActive"), OLESTR(""));
  839. hr = (m_isActive ? S_OK : S_FALSE);
  840. WsbTraceOut(OLESTR("CHsmJob::IsActive"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  841. return( hr );
  842. }
  843. HRESULT
  844. CHsmJob::IsUserDefined(
  845. void
  846. )
  847. /*++
  848. Implements:
  849. IHsmJob::IsUserDefined().
  850. --*/
  851. {
  852. return(m_isUserDefined ? S_OK : S_FALSE);
  853. }
  854. HRESULT
  855. CHsmJob::Load(
  856. IN IStream* pStream
  857. )
  858. /*++
  859. Implements:
  860. IPersistStream::Load().
  861. --*/
  862. {
  863. HRESULT hr = S_OK;
  864. CComPtr<IPersistStream> pPersistStream;
  865. BOOL hasA;
  866. CComPtr<IHsmJobWorkItemPriv> pWorkItem;
  867. CComPtr<IWsbEnum> pEnum;
  868. CComPtr<IWsbCreateLocalObject> pCreateObj;
  869. WsbTraceIn(OLESTR("CHsmJob::Load"), OLESTR(""));
  870. try {
  871. WsbAssert(0 != pStream, E_POINTER);
  872. WsbLoadFromStream(pStream, &m_hsmId);
  873. WsbLoadFromStream(pStream, &m_id);
  874. WsbLoadFromStream(pStream, &m_isUserDefined);
  875. WsbLoadFromStream(pStream, &m_runId);
  876. WsbLoadFromStream(pStream, &m_name, 0);
  877. WsbAffirm(memcmp(&GUID_NULL, &m_hsmId, sizeof(GUID)) != 0, JOB_E_NOTMANAGINGHSM);
  878. #if 0
  879. CComPtr<IHsmServer> pServer;
  880. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, m_hsmId, IID_IHsmServer, (void**) &pServer));
  881. WsbAssertHr(pServer->QueryInterface(IID_IWsbCreateLocalObject, (void**) &pCreateObj));
  882. #endif
  883. WsbLoadFromStream(pStream, &hasA);
  884. if (hasA) {
  885. m_pContext = 0;
  886. // WsbAssertHr(pCreateObj->CreateInstance(CLSID_CHsmJobContext, IID_IHsmJobContext, (void**) &m_pContext));
  887. WsbAssertHr(CoCreateInstance(CLSID_CHsmJobContext, NULL, CLSCTX_SERVER, IID_IHsmJobContext, (void**) &m_pContext));
  888. WsbAffirmHr(m_pContext->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  889. WsbAffirmHr(pPersistStream->Load(pStream));
  890. pPersistStream = 0;
  891. }
  892. WsbLoadFromStream(pStream, &hasA);
  893. if (hasA) {
  894. m_pDef = 0;
  895. // WsbAssertHr(pCreateObj->CreateInstance(CLSID_CHsmJobDef, IID_IHsmJobDef, (void**) &m_pDef));
  896. WsbAssertHr(CoCreateInstance(CLSID_CHsmJobDef, NULL, CLSCTX_SERVER, IID_IHsmJobDef, (void**) &m_pDef));
  897. WsbAffirmHr(m_pDef->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  898. WsbAffirmHr(pPersistStream->Load(pStream));
  899. pPersistStream = 0;
  900. }
  901. WsbAffirmHr(m_pWorkItems->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  902. WsbAffirmHr(pPersistStream->Load(pStream));
  903. pPersistStream = 0;
  904. // Tie the work items to the job.
  905. WsbAffirmHr(EnumWorkItems(&pEnum));
  906. hr = pEnum->First(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem);
  907. while (SUCCEEDED(hr)) {
  908. WsbAffirmHr(pWorkItem->Init((IHsmJob*) this));
  909. pWorkItem = 0;
  910. hr = pEnum->Next(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem);
  911. }
  912. if (WSB_E_NOTFOUND == hr) {
  913. hr = S_OK;
  914. }
  915. } WsbCatch(hr);
  916. WsbTraceOut(OLESTR("CHsmJob::Load"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  917. return(hr);
  918. }
  919. HRESULT
  920. CHsmJob::Pause(
  921. IN HSM_JOB_PHASE phase
  922. )
  923. /*++
  924. Implements:
  925. IHsmJob::Pause().
  926. --*/
  927. {
  928. HRESULT hr = S_OK;
  929. CComPtr<IHsmJobWorkItemPriv> pWorkItem;
  930. CComPtr<IHsmSession> pSession;
  931. CComPtr<IWsbEnum> pEnum;
  932. try {
  933. WsbLogEvent(JOB_MESSAGE_JOB_PAUSING, 0, NULL, (OLECHAR*) m_name, NULL);
  934. WsbAffirmHr(EnumWorkItems(&pEnum));
  935. // Tell all the session we have to resume the phase(s).
  936. for (hr = pEnum->First(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem);
  937. (hr == S_OK);
  938. hr = pEnum->Next(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem)) {
  939. WsbAffirmHr(pWorkItem->GetSession(&pSession));
  940. if (pSession != 0) {
  941. WsbAffirmHr(pSession->Pause(phase));
  942. if (phase == HSM_JOB_PHASE_ALL) {
  943. WsbAffirmHr(pWorkItem->SetState(HSM_JOB_STATE_PAUSING));
  944. }
  945. pSession = 0;
  946. }
  947. pWorkItem = 0;
  948. }
  949. if (hr == WSB_E_NOTFOUND) {
  950. hr = S_OK;
  951. }
  952. } WsbCatch(hr);
  953. return(hr);
  954. }
  955. HRESULT
  956. CHsmJob::Restart(
  957. void
  958. )
  959. /*++
  960. Implements:
  961. IHsmJob::Restart().
  962. Note:
  963. If a job is suspended, it is restarted from where it was otherwise it is
  964. restarted from the beginning. This is controlled by the parameter to
  965. UpdateWorkItems.
  966. --*/
  967. {
  968. HRESULT hr = S_OK;
  969. WsbTraceIn(OLESTR("CHsmJob::Restart"), OLESTR(""));
  970. try {
  971. BOOL RestartFromBeginning = TRUE;
  972. if (m_state == HSM_JOB_STATE_SUSPENDED) {
  973. // Verify that none of the active work items (i.e. items that were active when
  974. // the job was suspended) uses a volume that is in use now by another active job
  975. CComPtr<IHsmJobWorkItemPriv> pWorkItem;
  976. CComPtr<IWsbEnum> pEnum;
  977. GUID ResourceId;
  978. HRESULT hrEnum;
  979. WsbAffirmHr(EnumWorkItems(&pEnum));
  980. for (hrEnum = pEnum->First(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem);
  981. (hrEnum == S_OK);
  982. hrEnum = pEnum->Next(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem)) {
  983. hr = pWorkItem->IsActiveItem();
  984. if (S_FALSE == hr) {
  985. // work item is not active at all, skip it...
  986. hr = S_OK;
  987. pWorkItem = 0;
  988. continue;
  989. } else {
  990. WsbAffirmHr(hr);
  991. }
  992. // check specific active item
  993. WsbAffirmHr(pWorkItem->GetResourceId(&ResourceId));
  994. WsbTrace(OLESTR("CHsmJob::Restart: ResourceId = <%ls>\n"), WsbGuidAsString(ResourceId));
  995. hr = CheckResourceNotInUse(ResourceId);
  996. if (S_OK != hr) {
  997. WsbThrow(hr);
  998. }
  999. pWorkItem = 0;
  1000. }
  1001. RestartFromBeginning = FALSE;
  1002. } else {
  1003. WsbAssert(!m_isActive, JOB_E_ALREADYACTIVE);
  1004. }
  1005. m_state = HSM_JOB_STATE_STARTING;
  1006. m_isActive = TRUE;
  1007. WsbLogEvent(JOB_MESSAGE_JOB_RESTARTING, 0, NULL, (OLECHAR*) m_name, NULL);
  1008. // Make sure that information in the work list is up to date.
  1009. WsbAffirmHr(UpdateWorkItems(RestartFromBeginning));
  1010. // Start any sessions that need starting.
  1011. WsbAffirmHr(Do());
  1012. } WsbCatch(hr);
  1013. WsbTraceOut(OLESTR("CHsmJob::Restart"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1014. return(hr);
  1015. }
  1016. HRESULT
  1017. CHsmJob::RestartSuspendedJobs(
  1018. void
  1019. )
  1020. /*++
  1021. Routine Description:
  1022. Restart suspended jobs (Implementation moved to Engine server...).
  1023. Arguments:
  1024. None.
  1025. Return Value:
  1026. S_OK - Resource is not in use.
  1027. E_* - An error occurred.
  1028. --*/
  1029. {
  1030. HRESULT hr = S_OK;
  1031. WsbTraceIn(OLESTR("CHsmJob::RestartSuspendedJobs"), OLESTR(""));
  1032. try {
  1033. CComPtr<IHsmServer> pHsmServer;
  1034. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, m_hsmId, IID_IHsmServer, (void**) &pHsmServer));
  1035. WsbAffirmHr(pHsmServer->RestartSuspendedJobs());
  1036. } WsbCatch(hr);
  1037. WsbTraceOut(OLESTR("CHsmJob::RestartSuspendedJobs"), OLESTR("hr = <%ls>"),
  1038. WsbHrAsString(hr));
  1039. return(hr);
  1040. }
  1041. HRESULT
  1042. CHsmJob::Resume(
  1043. IN HSM_JOB_PHASE phase
  1044. )
  1045. /*++
  1046. Implements:
  1047. IHsmJob::Resume().
  1048. --*/
  1049. {
  1050. HRESULT hr = S_OK;
  1051. CComPtr<IHsmJobWorkItemPriv> pWorkItem;
  1052. CComPtr<IHsmSession> pSession;
  1053. CComPtr<IWsbEnum> pEnum;
  1054. try {
  1055. WsbLogEvent(JOB_MESSAGE_JOB_RESUMING, 0, NULL, (OLECHAR*) m_name, NULL);
  1056. WsbAffirmHr(EnumWorkItems(&pEnum));
  1057. // Tell all the session we have to resume the phase(s).
  1058. for (hr = pEnum->First(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem);
  1059. (hr == S_OK);
  1060. hr = pEnum->Next(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem)) {
  1061. WsbAffirmHr(pWorkItem->GetSession(&pSession));
  1062. if (pSession != 0) {
  1063. WsbAffirmHr(pSession->Resume(phase));
  1064. if (phase == HSM_JOB_PHASE_ALL) {
  1065. WsbAffirmHr(pWorkItem->SetState(HSM_JOB_STATE_RESUMING));
  1066. }
  1067. pSession = 0;
  1068. }
  1069. pWorkItem = 0;
  1070. }
  1071. if (hr == WSB_E_NOTFOUND) {
  1072. hr = S_OK;
  1073. }
  1074. } WsbCatch(hr);
  1075. return(hr);
  1076. }
  1077. HRESULT
  1078. CHsmJob::Save(
  1079. IN IStream* pStream,
  1080. IN BOOL clearDirty
  1081. )
  1082. /*++
  1083. Implements:
  1084. IPersistStream::Save().
  1085. --*/
  1086. {
  1087. HRESULT hr = S_OK;
  1088. CComPtr<IPersistStream> pPersistStream;
  1089. BOOL hasA;
  1090. WsbTraceIn(OLESTR("CHsmJob::Save"), OLESTR("clearDirty = <%ls>"), WsbBoolAsString(clearDirty));
  1091. try {
  1092. WsbAssert(0 != pStream, E_POINTER);
  1093. WsbSaveToStream(pStream, m_hsmId);
  1094. WsbSaveToStream(pStream, m_id);
  1095. WsbSaveToStream(pStream, m_isUserDefined);
  1096. WsbSaveToStream(pStream, m_runId);
  1097. WsbSaveToStream(pStream, m_name);
  1098. if (m_pContext != 0) {
  1099. hasA = TRUE;
  1100. WsbSaveToStream(pStream, hasA);
  1101. WsbAffirmHr(m_pContext->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  1102. WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
  1103. pPersistStream = 0;
  1104. } else {
  1105. hasA = FALSE;
  1106. WsbSaveToStream(pStream, hasA);
  1107. }
  1108. if (m_pDef != 0) {
  1109. hasA = TRUE;
  1110. WsbSaveToStream(pStream, hasA);
  1111. WsbAffirmHr(m_pDef->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  1112. WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
  1113. pPersistStream = 0;
  1114. } else {
  1115. hasA = FALSE;
  1116. WsbSaveToStream(pStream, hasA);
  1117. }
  1118. WsbAffirmHr(m_pWorkItems->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  1119. WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
  1120. pPersistStream = 0;
  1121. // If we got it saved and we were asked to clear the dirty bit, then
  1122. // do so now.
  1123. if (clearDirty) {
  1124. m_isDirty = FALSE;
  1125. }
  1126. } WsbCatch(hr);
  1127. WsbTraceOut(OLESTR("CHsmJob::Save"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1128. return(hr);
  1129. }
  1130. HRESULT
  1131. CHsmJob::SetContext(
  1132. IN IHsmJobContext* pContext
  1133. )
  1134. /*++
  1135. Implements:
  1136. IHsmJob::SetContext().
  1137. --*/
  1138. {
  1139. m_pContext = pContext;
  1140. return(S_OK);
  1141. }
  1142. HRESULT
  1143. CHsmJob::SetDef(
  1144. IN IHsmJobDef* pDef
  1145. )
  1146. /*++
  1147. Implements:
  1148. IHsmJob::SetDef().
  1149. --*/
  1150. {
  1151. m_pDef = pDef;
  1152. return(S_OK);
  1153. }
  1154. HRESULT
  1155. CHsmJob::SetHsmId(
  1156. IN GUID id
  1157. )
  1158. /*++
  1159. Implements:
  1160. IHsmJob::SetHsmId().
  1161. --*/
  1162. {
  1163. m_hsmId = id;
  1164. return(S_OK);
  1165. }
  1166. HRESULT
  1167. CHsmJob::SetIsUserDefined(
  1168. IN BOOL isUserDefined
  1169. )
  1170. /*++
  1171. Implements:
  1172. IHsmJob::SetIsUserDefined().
  1173. --*/
  1174. {
  1175. m_isUserDefined = isUserDefined;
  1176. return(S_OK);
  1177. }
  1178. HRESULT
  1179. CHsmJob::SetName(
  1180. IN OLECHAR* name
  1181. )
  1182. /*++
  1183. Implements:
  1184. IHsmJob::SetName().
  1185. --*/
  1186. {
  1187. HRESULT hr = S_OK;
  1188. try {
  1189. m_name = name;
  1190. } WsbCatch(hr);
  1191. return(hr);
  1192. }
  1193. HRESULT
  1194. CHsmJob::Start(
  1195. void
  1196. )
  1197. /*++
  1198. Implements:
  1199. IHsmJob::Start().
  1200. --*/
  1201. {
  1202. HRESULT hr = S_OK;
  1203. WsbTraceIn(OLESTR("CHsmJob::Start"), OLESTR(""));
  1204. try {
  1205. if (m_isActive) {
  1206. WsbLogEvent(JOB_MESSAGE_JOB_ALREADYACTIVE, 0, NULL, (OLECHAR*) m_name, NULL);
  1207. WsbThrow(JOB_E_ALREADYACTIVE);
  1208. }
  1209. m_isActive = TRUE;
  1210. m_state = HSM_JOB_STATE_STARTING;
  1211. WsbLogEvent(JOB_MESSAGE_JOB_STARTING, 0, NULL, (OLECHAR*) m_name, NULL);
  1212. // Make sure that information in the work list is up to date.
  1213. WsbAffirmHr(UpdateWorkItems(FALSE));
  1214. // Start any sessions that need starting.
  1215. WsbAffirmHr(Do());
  1216. } WsbCatch(hr);
  1217. WsbTraceOut(OLESTR("CHsmJob::Start"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1218. return(hr);
  1219. }
  1220. HRESULT
  1221. CHsmJob::Suspend(
  1222. IN HSM_JOB_PHASE phase
  1223. )
  1224. /*++
  1225. Implements:
  1226. IHsmJob::Suspend().
  1227. Note:
  1228. This module assumes that the only reason this function is called is
  1229. because the resource needed by the job is in use by another job.
  1230. The function RestartSuspendedJobs will restart the job when the resource
  1231. is available.
  1232. --*/
  1233. {
  1234. HRESULT hr = S_OK;
  1235. CComPtr<IHsmJobWorkItemPriv> pWorkItem;
  1236. CComPtr<IHsmSession> pSession;
  1237. CComPtr<IWsbEnum> pEnum;
  1238. WsbTraceIn(OLESTR("CHsmJob::Suspend"), OLESTR(""));
  1239. try {
  1240. m_state = HSM_JOB_STATE_SUSPENDING;
  1241. WsbLogEvent(JOB_MESSAGE_JOB_SUSPENDING, 0, NULL, (OLECHAR*) m_name, NULL);
  1242. WsbAffirmHr(EnumWorkItems(&pEnum));
  1243. // Tell all the sessions we have to suspend the phase(s).
  1244. for (hr = pEnum->First(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem);
  1245. (hr == S_OK);
  1246. hr = pEnum->Next(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem)) {
  1247. WsbAffirmHr(pWorkItem->GetSession(&pSession));
  1248. if (pSession != 0) {
  1249. WsbAffirmHr(pSession->Suspend(HSM_JOB_PHASE_ALL));
  1250. if (phase == HSM_JOB_PHASE_ALL) {
  1251. WsbAffirmHr(pWorkItem->SetState(HSM_JOB_STATE_SUSPENDING));
  1252. }
  1253. pSession = 0;
  1254. }
  1255. pWorkItem = 0;
  1256. }
  1257. if (hr == WSB_E_NOTFOUND) {
  1258. hr = S_OK;
  1259. }
  1260. m_state = HSM_JOB_STATE_SUSPENDED;
  1261. } WsbCatch(hr);
  1262. WsbTraceOut(OLESTR("CHsmJob::Suspend"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1263. return(hr);
  1264. }
  1265. HRESULT
  1266. CHsmJob::Test(
  1267. OUT USHORT* passed,
  1268. OUT USHORT* failed
  1269. )
  1270. /*++
  1271. Implements:
  1272. IWsbTestable::Test().
  1273. --*/
  1274. {
  1275. HRESULT hr = S_OK;
  1276. try {
  1277. WsbAssert(0 != passed, E_POINTER);
  1278. WsbAssert(0 != failed, E_POINTER);
  1279. *passed = 0;
  1280. *failed = 0;
  1281. } WsbCatch(hr);
  1282. return(hr);
  1283. }
  1284. HRESULT
  1285. CHsmJob::UpdateWorkItems(
  1286. BOOL isRestart
  1287. )
  1288. /*++
  1289. --*/
  1290. {
  1291. HRESULT hr = S_OK;
  1292. CComPtr<IWsbEnum> pEnum;
  1293. CComPtr<IWsbEnum> pEnumContext;
  1294. CComPtr<IWsbEnum> pEnumManaged;
  1295. CComPtr<IWsbIndexedCollection> pManagedResources;
  1296. CComPtr<IHsmJobWorkItemPriv> pWorkItem;
  1297. CComPtr<IHsmJobWorkItemPriv> pFoundWorkItem;
  1298. CComPtr<IWsbGuid> pGuid;
  1299. CComPtr<IWsbGuid> pFoundGuid;
  1300. CComPtr<IHsmManagedResource> pManagedResource;
  1301. CComPtr<IHsmManagedResource> pFoundResource;
  1302. CComPtr<IHsmServer> pHsmServer;
  1303. CComPtr<IWsbCollection> pCollect;
  1304. CComPtr<IFsaResource> pResource;
  1305. CComPtr<IUnknown> pUnk;
  1306. HRESULT didFinish;
  1307. CWsbStringPtr tmpString;
  1308. CWsbStringPtr currentPath;
  1309. HSM_JOB_STATE state;
  1310. GUID id;
  1311. try {
  1312. // We can't run a job without a context and a definition.
  1313. WsbAssert(m_pContext != 0, E_UNEXPECTED);
  1314. WsbAssert(m_pDef != 0, E_UNEXPECTED);
  1315. // Get an enumerator for the work list.
  1316. WsbAffirmHr(EnumWorkItems(&pEnum));
  1317. // First we need to remove any items from the work list that are no longer listed
  1318. // or have been deactivated.
  1319. if (m_pContext->UsesAllManaged() == S_OK) {
  1320. WsbAffirm(memcmp(&GUID_NULL, &m_hsmId, sizeof(GUID)) != 0, JOB_E_NOTMANAGINGHSM);
  1321. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, m_hsmId, IID_IHsmServer, (void**) &pHsmServer));
  1322. WsbAffirmHr(pHsmServer->GetManagedResources(&pManagedResources));
  1323. WsbAffirmHr(pManagedResources->Enum(&pEnumManaged));
  1324. WsbAffirmHr(CoCreateInstance(CLSID_CHsmManagedResource, 0, CLSCTX_ALL, IID_IHsmManagedResource, (void**) &pManagedResource));
  1325. hr = pEnum->First(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem);
  1326. while (SUCCEEDED(hr)) {
  1327. WsbAffirmHr(pWorkItem->GetResourceId(&id));
  1328. WsbAffirmHr(pManagedResource->SetResourceId(id));
  1329. if (pEnumManaged->Find(pManagedResource, IID_IHsmManagedResource, (void**) &pFoundResource) == WSB_E_NOTFOUND) {
  1330. hr = S_OK;
  1331. m_pWorkItems->RemoveAndRelease(pWorkItem);
  1332. pWorkItem = 0;
  1333. hr = pEnum->This(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem);
  1334. } else {
  1335. pFoundResource = 0;
  1336. pWorkItem = 0;
  1337. hr = pEnum->Next(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem);
  1338. }
  1339. }
  1340. pManagedResource = 0;
  1341. if (hr == WSB_E_NOTFOUND) {
  1342. hr = S_OK;
  1343. }
  1344. } else {
  1345. WsbAffirmHr(m_pContext->EnumResources(&pEnumContext));
  1346. WsbAffirmHr(CoCreateInstance(CLSID_CWsbGuid, 0, CLSCTX_ALL, IID_IWsbGuid, (void**) &pGuid));
  1347. hr = pEnum->First(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem);
  1348. while (SUCCEEDED(hr)) {
  1349. WsbAffirmHr(pWorkItem->GetResourceId(&id));
  1350. WsbAffirmHr(pGuid->SetGuid(id));
  1351. if (pEnumContext->Find(pGuid, IID_IWsbGuid, (void**) &pFoundGuid) == WSB_E_NOTFOUND) {
  1352. hr = S_OK;
  1353. m_pWorkItems->RemoveAndRelease(pWorkItem);
  1354. pWorkItem = 0;
  1355. hr = pEnum->This(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem);
  1356. } else {
  1357. pWorkItem = 0;
  1358. pFoundGuid = 0;
  1359. hr = pEnum->Next(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem);
  1360. }
  1361. }
  1362. pGuid = 0;
  1363. if (hr == WSB_E_NOTFOUND) {
  1364. hr = S_OK;
  1365. }
  1366. }
  1367. // Based on the items that remain, determine whether this is a restart or a
  1368. // continuation.
  1369. WsbAffirmHr(didFinish = DidFinish());
  1370. if ((didFinish == S_OK) || (isRestart)) {
  1371. isRestart = TRUE;
  1372. m_runId++;
  1373. }
  1374. // Add new work items for any items that are new or reactivated.
  1375. if (m_pContext->UsesAllManaged() == S_OK) {
  1376. // Enumerate all the managed resources, and make sure that they are listed
  1377. // as work items.
  1378. WsbAffirmHr(CoCreateInstance(CLSID_CHsmJobWorkItem, 0, CLSCTX_ALL, IID_IHsmJobWorkItemPriv, (void**) &pWorkItem));
  1379. for (hr = pEnumManaged->First(IID_IHsmManagedResource, (void**) &pManagedResource);
  1380. (hr == S_OK);
  1381. pManagedResource = 0, hr = pEnumManaged->Next(IID_IHsmManagedResource, (void**) &pManagedResource)) {
  1382. WsbAffirmHr(pManagedResource->GetFsaResource(&pUnk));
  1383. WsbAffirmHr(pUnk->QueryInterface(IID_IFsaResource, (void**) &pResource));
  1384. WsbAffirmHr(pResource->GetIdentifier(&id));
  1385. WsbAffirmHr(pWorkItem->SetResourceId(id));
  1386. pFoundWorkItem = 0;
  1387. if (pEnum->Find(pWorkItem, IID_IHsmJobWorkItemPriv, (void**) &pFoundWorkItem) == WSB_E_NOTFOUND) {
  1388. hr = S_OK;
  1389. WsbAffirmHr(pWorkItem->Init((IHsmJob*) this));
  1390. WsbAffirmHr(m_pWorkItems->Add(pWorkItem));
  1391. pWorkItem = 0;
  1392. WsbAffirmHr(CoCreateInstance(CLSID_CHsmJobWorkItem, 0, CLSCTX_ALL, IID_IHsmJobWorkItemPriv, (void**) &pWorkItem));
  1393. }
  1394. pUnk = 0;
  1395. pResource = 0;
  1396. }
  1397. if (hr == WSB_E_NOTFOUND) {
  1398. hr = S_OK;
  1399. }
  1400. } else {
  1401. // Enumerate all the resources in the context, and make sure that they are listed
  1402. // as work items.
  1403. WsbAffirmHr(CoCreateInstance(CLSID_CHsmJobWorkItem, 0, CLSCTX_ALL, IID_IHsmJobWorkItemPriv, (void**) &pWorkItem));
  1404. for (hr = pEnumContext->First(IID_IWsbGuid, (void**) &pGuid);
  1405. (hr == S_OK);
  1406. hr = pEnumContext->Next(IID_IWsbGuid, (void**) &pGuid)) {
  1407. WsbAffirmHr(pGuid->GetGuid(&id));
  1408. WsbAffirmHr(pWorkItem->SetResourceId(id));
  1409. pFoundWorkItem = 0;
  1410. if (pEnum->Find(pWorkItem, IID_IHsmJobWorkItemPriv, (void**) &pFoundWorkItem) == WSB_E_NOTFOUND) {
  1411. hr = S_OK;
  1412. WsbAffirmHr(pWorkItem->Init((IHsmJob*) this));
  1413. WsbAffirmHr(m_pWorkItems->Add(pWorkItem));
  1414. pWorkItem = 0;
  1415. WsbAffirmHr(CoCreateInstance(CLSID_CHsmJobWorkItem, 0, CLSCTX_ALL, IID_IHsmJobWorkItemPriv, (void**) &pWorkItem));
  1416. }
  1417. pGuid = 0;
  1418. }
  1419. if (hr == WSB_E_NOTFOUND) {
  1420. hr = S_OK;
  1421. }
  1422. }
  1423. pWorkItem = 0;
  1424. // Check each item to see if work needs to be done for it.
  1425. for (hr = pEnum->First(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem);
  1426. (hr == S_OK);
  1427. hr = pEnum->Next(IID_IHsmJobWorkItemPriv, (void**) &pWorkItem)) {
  1428. // Resources should be skipped if they are inactive, unavailable or in need of repair. If they
  1429. // had been skipped but are ok now, then set them back to idle.
  1430. WsbAffirmHr(pWorkItem->GetResourceId(&id));
  1431. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_RESOURCE, id, IID_IFsaResource, (void**) &pResource));
  1432. WsbAffirmHr(pWorkItem->GetState(&state));
  1433. if (pResource->IsActive() != S_OK) {
  1434. WsbAffirmHr(pResource->GetUserFriendlyName(&tmpString, 0));
  1435. WsbLogEvent(JOB_MESSAGE_RESOURCE_INACTIVE, 0, NULL, (OLECHAR*) tmpString, (OLECHAR*) m_name, NULL);
  1436. WsbAffirmHr(pWorkItem->SetState(HSM_JOB_STATE_SKIPPED));
  1437. } else if (pResource->IsAvailable() != S_OK) {
  1438. WsbAffirmHr(pResource->GetUserFriendlyName(&tmpString, 0));
  1439. WsbLogEvent(JOB_MESSAGE_RESOURCE_UNAVAILABLE, 0, NULL, (OLECHAR*) tmpString, (OLECHAR*) m_name, NULL);
  1440. WsbAffirmHr(pWorkItem->SetState(HSM_JOB_STATE_SKIPPED));
  1441. } else if (pResource->NeedsRepair() == S_OK) {
  1442. WsbAffirmHr(pResource->GetUserFriendlyName(&tmpString, 0));
  1443. WsbLogEvent(JOB_MESSAGE_RESOURCE_NEEDS_REPAIR, 0, NULL, (OLECHAR*) tmpString, (OLECHAR*) m_name, NULL);
  1444. WsbAffirmHr(pWorkItem->SetState(HSM_JOB_STATE_SKIPPED));
  1445. } else if (HSM_JOB_STATE_SKIPPED == state) {
  1446. WsbAffirmHr(pWorkItem->SetState(HSM_JOB_STATE_IDLE));
  1447. }
  1448. WsbAffirmHr(pWorkItem->GetState(&state));
  1449. // Don't do anything for inactive resources.
  1450. if (HSM_JOB_STATE_SKIPPED != state) {
  1451. if (isRestart) {
  1452. // On a restart, all items need work to be done for them.
  1453. //
  1454. // NOTE: A null starting path means the root.
  1455. WsbAffirmHr(pWorkItem->SetState(HSM_JOB_STATE_IDLE));
  1456. WsbAffirmHr(pWorkItem->SetSubRunId(0));
  1457. WsbAffirmHr(pWorkItem->SetStartingPath(OLESTR("\\")));
  1458. WsbAffirmHr(pWorkItem->SetCurrentPath(OLESTR("\\")));
  1459. // Clear out the phases and session totals.
  1460. pCollect = 0;
  1461. WsbAffirmHr(pWorkItem->GetPhases(&pCollect));
  1462. WsbAffirmHr(pCollect->RemoveAllAndRelease());
  1463. pCollect = 0;
  1464. WsbAffirmHr(pWorkItem->GetTotals(&pCollect));
  1465. WsbAffirmHr(pCollect->RemoveAllAndRelease());
  1466. } else {
  1467. // If we didn't finish it last time, then try it.
  1468. if ((HSM_JOB_STATE_DONE != state) && (HSM_JOB_STATE_FAILED != state)) {
  1469. WsbAffirmHr(pWorkItem->SetState(HSM_JOB_STATE_IDLE));
  1470. WsbAffirmHr(pWorkItem->SetSubRunId(0));
  1471. // If it was suspended, then begin where we left off. Otherwise,
  1472. // start from the beginning.
  1473. if (HSM_JOB_STATE_SUSPENDED == state) {
  1474. WsbAffirmHr(pWorkItem->GetCurrentPath(&currentPath, 0));
  1475. } else {
  1476. WsbAffirmHr(pWorkItem->SetCurrentPath(OLESTR("\\")));
  1477. }
  1478. WsbAffirmHr(pWorkItem->SetStartingPath(currentPath));
  1479. // Clear out the phases and session totals.
  1480. pCollect = 0;
  1481. WsbAffirmHr(pWorkItem->GetPhases(&pCollect));
  1482. WsbAffirmHr(pCollect->RemoveAllAndRelease());
  1483. pCollect = 0;
  1484. WsbAffirmHr(pWorkItem->GetTotals(&pCollect));
  1485. WsbAffirmHr(pCollect->RemoveAllAndRelease());
  1486. }
  1487. }
  1488. }
  1489. pResource = 0;
  1490. pWorkItem = 0;
  1491. }
  1492. if (hr == WSB_E_NOTFOUND) {
  1493. hr = S_OK;
  1494. }
  1495. } WsbCatch(hr);
  1496. return(hr);
  1497. }
  1498. HRESULT
  1499. CHsmJob::WaitUntilDone(
  1500. void
  1501. )
  1502. /*++
  1503. Implements:
  1504. IHsmJob::WaitUntilDone().
  1505. --*/
  1506. {
  1507. HRESULT hr = S_OK;
  1508. WsbTraceIn(OLESTR("CHsmJob::WaitUntilDone"), OLESTR(""));
  1509. try {
  1510. // For now, we are just going to be gross about this, and sit in a sleep loop
  1511. // until the job finishes.
  1512. //
  1513. // NOTE: We may want to do with events or something.
  1514. while (m_isActive) {
  1515. Sleep(5000);
  1516. // Make sure the job gets restarted if it is suspended
  1517. WsbAffirmHr(RestartSuspendedJobs());
  1518. }
  1519. } WsbCatch(hr);
  1520. WsbTraceOut(OLESTR("CHsmJob::WaitUntilDone"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1521. return(hr);
  1522. }