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.

1355 lines
39 KiB

  1. /*++
  2. 1998 Seagate Software, Inc. All rights reserved.
  3. Module Name:
  4. tskmgr.cpp
  5. Abstract:
  6. This class represents the HSM task manager
  7. Author:
  8. Cat Brant [cbrant] 6-Dec-1996
  9. Revision History:
  10. Incorporate demand recall queue support
  11. - Ravisankar Pudipeddi [ravisp] 1-Oct-199
  12. --*/
  13. #include "stdafx.h"
  14. #define WSB_TRACE_IS WSB_TRACE_BIT_HSMTSKMGR
  15. #include "wsb.h"
  16. #include "hsmconn.h"
  17. #include "hsmeng.h"
  18. #include "fsa.h"
  19. #include "task.h"
  20. #include "tskmgr.h"
  21. #include "hsmWorkQ.h"
  22. #include "engine.h"
  23. #define MAX_WORK_QUEUE_TYPES 7
  24. HRESULT
  25. CHsmTskMgr::FinalConstruct(
  26. void
  27. )
  28. /*++
  29. Routine Description:
  30. This method does some initialization of the object that is necessary
  31. after construction.
  32. Arguments:
  33. None.
  34. Return Value:
  35. S_OK
  36. Anything returned by CWsbCollectable::FinalConstruct().
  37. --*/
  38. {
  39. HRESULT hr = S_OK;
  40. WsbTraceIn(OLESTR("CHsmTskMgr::FinalConstruct"),OLESTR(""));
  41. try {
  42. m_bCritSecCreated = FALSE;
  43. int index = 0;
  44. WsbAssertHr(CComObjectRoot::FinalConstruct());
  45. m_pWorkQueues = 0;
  46. m_NumWorkQueues = 0;
  47. // Set up queue type info and set limits
  48. m_nWorkQueueTypes = 0;
  49. m_pWorkQueueTypeInfo = static_cast<PHSM_WORK_QUEUE_TYPE_INFO>
  50. (WsbAlloc(MAX_WORK_QUEUE_TYPES *
  51. sizeof(HSM_WORK_QUEUE_TYPE_INFO)));
  52. WsbAffirmPointer(m_pWorkQueueTypeInfo);
  53. // Migrate queues
  54. WsbAffirm(index < MAX_WORK_QUEUE_TYPES, WSB_E_INVALID_DATA);
  55. m_pWorkQueueTypeInfo[index].Type = HSM_WORK_TYPE_FSA_MIGRATE;
  56. m_pWorkQueueTypeInfo[index].MaxActiveAllowed = 1; // For Migrate, this is useless now
  57. // - the limit is dynamically set
  58. m_pWorkQueueTypeInfo[index].NumActive = 0;
  59. index++;
  60. // Recall queues
  61. WsbAffirm(index < MAX_WORK_QUEUE_TYPES, WSB_E_INVALID_DATA);
  62. m_pWorkQueueTypeInfo[index].Type = HSM_WORK_TYPE_FSA_RECALL;
  63. m_pWorkQueueTypeInfo[index].MaxActiveAllowed = 1;
  64. m_pWorkQueueTypeInfo[index].NumActive = 0;
  65. index++;
  66. // Demand Recall queues
  67. WsbAffirm(index < MAX_WORK_QUEUE_TYPES, WSB_E_INVALID_DATA);
  68. m_pWorkQueueTypeInfo[index].Type = HSM_WORK_TYPE_FSA_DEMAND_RECALL;
  69. //
  70. // MaxActiveAllowed is irrelevant for demand recall queues
  71. // as it is computed afresh
  72. //
  73. m_pWorkQueueTypeInfo[index].MaxActiveAllowed = 1;
  74. m_pWorkQueueTypeInfo[index].NumActive = 0;
  75. index++;
  76. // Validate queues
  77. WsbAffirm(index < MAX_WORK_QUEUE_TYPES, WSB_E_INVALID_DATA);
  78. m_pWorkQueueTypeInfo[index].Type = HSM_WORK_TYPE_FSA_VALIDATE;
  79. m_pWorkQueueTypeInfo[index].MaxActiveAllowed = 2;
  80. m_pWorkQueueTypeInfo[index].NumActive = 0;
  81. index++;
  82. // Validate_for_truncate queues. MaxActiveAllowed is essentially
  83. // unlimited because this is the type of queue that the FSA's
  84. // auto-truncator creates. Because there is one queue for each managed
  85. // volume and these queues never go away, we can't limit the number
  86. // or we will create problems. The Truncate job also
  87. // creates this type of queue which means that type of job is not
  88. // limited by this mechanism, but that's the way it goes.
  89. WsbAffirm(index < MAX_WORK_QUEUE_TYPES, WSB_E_INVALID_DATA);
  90. m_pWorkQueueTypeInfo[index].Type = HSM_WORK_TYPE_FSA_VALIDATE_FOR_TRUNCATE;
  91. m_pWorkQueueTypeInfo[index].MaxActiveAllowed = 99999;
  92. m_pWorkQueueTypeInfo[index].NumActive = 0;
  93. index++;
  94. m_nWorkQueueTypes = index;
  95. }WsbCatch(hr);
  96. WsbTraceOut(OLESTR("CHsmTskMgr::FinalConstruct"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
  97. return(hr);
  98. }
  99. HRESULT
  100. CHsmTskMgr::FinalRelease(
  101. void
  102. )
  103. /*++
  104. Routine Description:
  105. This method does some clean up of the object that is necessary
  106. before destruction.
  107. Arguments:
  108. None.
  109. Return Value:
  110. S_OK
  111. Anything returned by CWsbCollection::FinalRelease().
  112. --*/
  113. {
  114. HRESULT hr = S_OK;
  115. HSM_SYSTEM_STATE SysState;
  116. WsbTraceIn(OLESTR("CHsmTskMgr::FinalRelease"),OLESTR(""));
  117. SysState.State = HSM_STATE_SHUTDOWN;
  118. ChangeSysState(&SysState);
  119. CComObjectRoot::FinalRelease();
  120. // Free member resources
  121. if (0 != m_pWorkQueues) {
  122. WsbFree(m_pWorkQueues);
  123. m_pWorkQueues = NULL;
  124. }
  125. if (m_pWorkQueueTypeInfo) {
  126. WsbFree(m_pWorkQueueTypeInfo);
  127. m_pWorkQueueTypeInfo = NULL;
  128. }
  129. m_nWorkQueueTypes = 0;
  130. if (m_bCritSecCreated) {
  131. DeleteCriticalSection(&m_WorkQueueLock);
  132. DeleteCriticalSection(&m_CurrentRunningLock);
  133. DeleteCriticalSection(&m_CreateWorkQueueLock);
  134. }
  135. WsbTraceOut(OLESTR("CHsmTskMgr::FinalRelease"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
  136. return(hr);
  137. }
  138. HRESULT
  139. CHsmTskMgr::Init(
  140. IUnknown *pServer
  141. )
  142. /*++
  143. Routine Description:
  144. This method does some initialization of the object that is necessary
  145. after construction.
  146. Arguments:
  147. None.
  148. Return Value:
  149. S_OK
  150. --*/
  151. {
  152. HRESULT hr = S_OK;
  153. WsbTraceIn(OLESTR("CHsmTskMgr::Init"),OLESTR(""));
  154. try {
  155. // Initialize critical sections
  156. WsbAffirmStatus(InitializeCriticalSectionAndSpinCount (&m_WorkQueueLock, 1000));
  157. if (! InitializeCriticalSectionAndSpinCount (&m_CurrentRunningLock, 1000)) {
  158. DWORD dwErr = GetLastError();
  159. hr = HRESULT_FROM_WIN32(dwErr);
  160. DeleteCriticalSection(&m_WorkQueueLock);
  161. WsbAffirmHr(hr);
  162. }
  163. if (! InitializeCriticalSectionAndSpinCount (&m_CreateWorkQueueLock, 1000)) {
  164. DWORD dwErr = GetLastError();
  165. hr = HRESULT_FROM_WIN32(dwErr);
  166. DeleteCriticalSection(&m_WorkQueueLock);
  167. DeleteCriticalSection(&m_CurrentRunningLock);
  168. WsbAffirmHr(hr);
  169. }
  170. m_bCritSecCreated = TRUE;
  171. //
  172. // Get the server interface
  173. //
  174. WsbAffirmHr(pServer->QueryInterface(IID_IHsmServer, (void **)&m_pServer));
  175. //We want a weak link to the server so decrement the reference count
  176. m_pServer->Release();
  177. WsbAffirmHr(m_pServer->QueryInterface(IID_IWsbCreateLocalObject, (void **)&m_pHsmServerCreate));
  178. // We want a weak link to the server so decrement the reference count
  179. m_pHsmServerCreate->Release();
  180. // Go ahead and preallocate some space for the work queues
  181. WsbAffirmHr(IncreaseWorkQueueArraySize(HsmWorkQueueArrayBumpSize));
  182. }WsbCatch( hr );
  183. WsbTraceOut(OLESTR("CHsmTskMgr::Init"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
  184. return( hr );
  185. }
  186. HRESULT
  187. CHsmTskMgr::ContactOk(
  188. void
  189. )
  190. /*++
  191. Routine Description:
  192. This allows the caller to see if the RPC connection
  193. to the task manager is OK
  194. Arguments:
  195. None.
  196. Return Value:
  197. S_OK
  198. --*/
  199. {
  200. return( S_OK );
  201. }
  202. HRESULT
  203. CHsmTskMgr::DoFsaWork(
  204. IFsaPostIt *pFsaWorkItem
  205. )
  206. /*++
  207. Implements:
  208. IHsmFsaTskMgr::DoFsaWork
  209. --*/
  210. {
  211. HRESULT hr = S_OK;
  212. CComPtr<IHsmSession> pSession;
  213. CComPtr<IHsmWorkQueue> pWorkQueue;
  214. CComPtr<IHsmRecallQueue> pRecallQueue;
  215. FSA_REQUEST_ACTION workAction;
  216. GUID mediaId;
  217. LONGLONG dataSetStart;
  218. WsbTraceIn(OLESTR("CHsmTskMgr::DoFsaWork"),OLESTR(""));
  219. try {
  220. CWsbStringPtr path;
  221. LONGLONG fileVersionId;
  222. FSA_PLACEHOLDER placeholder;
  223. GUID hsmId, bagId;
  224. BOOL bCreated;
  225. // Get the version Id from the work Item.
  226. WsbAffirmHr(pFsaWorkItem->GetFileVersionId(&fileVersionId));
  227. // Get the placeholder from the work item
  228. WsbAffirmHr(pFsaWorkItem->GetPlaceholder(&placeholder));
  229. // Get the HSM ID from the server
  230. WsbAffirmHr(m_pServer->GetID(&hsmId));
  231. //
  232. // Make sure this instance of the engine managed the file
  233. //
  234. if ((GUID_NULL != placeholder.hsmId) && (hsmId != placeholder.hsmId)) {
  235. CWsbStringPtr path;
  236. (void)pFsaWorkItem->GetPath(&path, 0);
  237. hr = HSM_E_FILE_MANAGED_BY_DIFFERENT_HSM;
  238. WsbLogEvent(HSM_MESSAGE_FILE_MANAGED_BY_DIFFERENT_HSM, 0, NULL, WsbAbbreviatePath(path, 120), WsbHrAsString(hr), NULL);
  239. WsbThrow(hr);
  240. }
  241. //
  242. // Make sure there is a work allocater for this session
  243. //
  244. WsbAffirmHr(pFsaWorkItem->GetPath(&path, 0));
  245. WsbAffirmHr(pFsaWorkItem->GetSession(&pSession));
  246. WsbAffirmHr(pFsaWorkItem->GetRequestAction(&workAction));
  247. WsbTrace(OLESTR("CHsmTskMgr::DoFsaWork for <%ls> for <%lu>.\n"), (WCHAR *)path, workAction);
  248. if ((workAction == FSA_REQUEST_ACTION_FILTER_RECALL) ||
  249. (workAction == FSA_REQUEST_ACTION_FILTER_READ)) {
  250. WsbAffirmHr(FindRecallMediaToUse(pFsaWorkItem, &mediaId, &bagId, &dataSetStart));
  251. WsbAffirmHr(AddToRecallQueueForFsaSession(pSession,&pRecallQueue, &bCreated, &mediaId, &bagId, dataSetStart, pFsaWorkItem));
  252. } else {
  253. WsbAffirmHr(EnsureQueueForFsaSession(pSession, workAction, &pWorkQueue, &bCreated));
  254. //
  255. // Give the work to a queue
  256. //
  257. WsbAffirmHr(pWorkQueue->Add(pFsaWorkItem));
  258. }
  259. //
  260. // Start any queues that qualify (performance: only when a new queue is created)
  261. //
  262. if (bCreated) {
  263. WsbAffirmHr(StartQueues());
  264. }
  265. }WsbCatch (hr);
  266. WsbTraceOut(OLESTR("CHsmTskMgr::DoFsaWork"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
  267. return(hr);
  268. }
  269. HRESULT
  270. CHsmTskMgr::EnsureQueueForFsaSession(
  271. IN IHsmSession *pSession,
  272. IN FSA_REQUEST_ACTION fsaAction,
  273. OUT IHsmWorkQueue **ppWorkQueue,
  274. OUT BOOL *bCreated
  275. )
  276. /*++
  277. --*/
  278. {
  279. HRESULT hr = S_OK;
  280. HSM_WORK_QUEUE_STATE state;
  281. ULONG index;
  282. CComPtr<IHsmSession> l_pSession;
  283. HSM_WORK_QUEUE_TYPE type1=HSM_WORK_TYPE_NONE;
  284. HSM_WORK_QUEUE_TYPE type2;
  285. FILETIME birthDate;
  286. SYSTEMTIME systemTime;
  287. GUID sessionGuid;
  288. WsbTraceIn(OLESTR("CHsmTskMgr::EnsureQueueForFsaSession"),OLESTR("FsaRequestAction = <%lu>, Waiting on CreateWorkQueueLock"), fsaAction);
  289. EnterCriticalSection(&m_CreateWorkQueueLock);
  290. try {
  291. WsbAffirm(0 != ppWorkQueue, E_POINTER);
  292. // Convert FSA action to work queue type
  293. switch (fsaAction) {
  294. case FSA_REQUEST_ACTION_FILTER_READ:
  295. case FSA_REQUEST_ACTION_FILTER_RECALL:
  296. //
  297. // Should not happen!! AddToRecallQueueForFsaSession is the
  298. // right interface for recall items
  299. //
  300. WsbThrow(E_INVALIDARG);
  301. break;
  302. case FSA_REQUEST_ACTION_RECALL:
  303. type1 = HSM_WORK_TYPE_FSA_RECALL;
  304. break;
  305. case FSA_REQUEST_ACTION_PREMIGRATE:
  306. type1 = HSM_WORK_TYPE_FSA_MIGRATE;
  307. break;
  308. case FSA_REQUEST_ACTION_VALIDATE:
  309. type1 = HSM_WORK_TYPE_FSA_VALIDATE;
  310. break;
  311. case FSA_REQUEST_ACTION_VALIDATE_FOR_TRUNCATE:
  312. type1 = HSM_WORK_TYPE_FSA_VALIDATE_FOR_TRUNCATE;
  313. break;
  314. default:
  315. hr = E_NOTIMPL;
  316. type1 = HSM_WORK_TYPE_NONE;
  317. break;
  318. }
  319. WsbTrace(OLESTR("CHsmTskMgr::EnsureQueueForFsaSession: type1 = %d\n"),
  320. static_cast<int>(type1));
  321. // Check the array of work queues and see if there is one for
  322. // this session.
  323. *bCreated = FALSE;
  324. hr = FindWorkQueueElement(pSession, type1, &index, NULL);
  325. if (hr == S_OK) {
  326. WsbAffirmHr(GetWorkQueueElement(index, &l_pSession, ppWorkQueue, &type2, &state, &birthDate));
  327. if ((l_pSession != pSession) || (type1 != type2)) {
  328. *ppWorkQueue = 0;
  329. WsbAssertHr(E_UNEXPECTED);
  330. }
  331. if (HSM_WORK_QUEUE_NONE == state) {
  332. WsbTrace(OLESTR("CHsmTskMgr::EnsureQueueForFsaSession: Creating new queue (state is NONE)\n"));
  333. WsbAffirmHr(m_pHsmServerCreate->CreateInstance(CLSID_CHsmWorkQueue, IID_IHsmWorkQueue,
  334. (void **)ppWorkQueue));
  335. WsbAffirmHr((*ppWorkQueue)->Init(m_pServer, pSession, (IHsmFsaTskMgr *)this, type1));
  336. GetSystemTime(&systemTime);
  337. WsbAffirmStatus(SystemTimeToFileTime(&systemTime, &birthDate));
  338. WsbAffirmHr(pSession->GetIdentifier(&sessionGuid));
  339. m_pWorkQueues[index].sessionId = sessionGuid;
  340. WsbAffirmHr(SetWorkQueueElement(index, pSession, *ppWorkQueue, type1, HSM_WORK_QUEUE_IDLE, birthDate));
  341. *bCreated = TRUE;
  342. }
  343. } else {
  344. if (hr == WSB_E_NOTFOUND) {
  345. hr = S_OK;
  346. WsbTrace(OLESTR("CHsmTskMgr::EnsureQueueForFsaSession: Creating new queue (queue not found)\n"));
  347. WsbAffirmHr(AddWorkQueueElement(pSession, type1, &index));
  348. // The work queue has not been created so create it
  349. WsbAffirmHr(m_pHsmServerCreate->CreateInstance(CLSID_CHsmWorkQueue, IID_IHsmWorkQueue,
  350. (void **)ppWorkQueue));
  351. WsbAffirmHr((*ppWorkQueue)->Init(m_pServer, pSession, (IHsmFsaTskMgr *)this, type1));
  352. GetSystemTime(&systemTime);
  353. WsbAffirmStatus(SystemTimeToFileTime(&systemTime, &birthDate));
  354. WsbAffirmHr(pSession->GetIdentifier(&sessionGuid));
  355. m_pWorkQueues[index].sessionId = sessionGuid;
  356. WsbAffirmHr(SetWorkQueueElement(index, pSession, *ppWorkQueue, type1, HSM_WORK_QUEUE_IDLE, birthDate));
  357. *bCreated = TRUE;
  358. }
  359. }
  360. }WsbCatch( hr );
  361. LeaveCriticalSection(&m_CreateWorkQueueLock);
  362. WsbTraceOut(OLESTR("CHsmTskMgr::EnsureQueueForFsaSession"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
  363. return(hr);
  364. }
  365. HRESULT
  366. CHsmTskMgr::AddToRecallQueueForFsaSession(
  367. IN IHsmSession *pSession,
  368. OUT IHsmRecallQueue **ppWorkQueue,
  369. OUT BOOL *bCreated,
  370. IN GUID *pMediaId,
  371. IN GUID *pBagId,
  372. IN LONGLONG dataSetStart,
  373. IN IFsaPostIt *pFsaWorkItem
  374. )
  375. /*++
  376. --*/
  377. {
  378. HRESULT hr = S_OK;
  379. WsbTraceIn(OLESTR("CHsmTskMgr::AddToRecallQueueForFsaSession"),OLESTR("Waiting on CreateWorkQueueLock"));
  380. EnterCriticalSection(&m_WorkQueueLock);
  381. try {
  382. WsbAffirm(0 != ppWorkQueue, E_POINTER);
  383. //
  384. // This call will find the queue if it's already present -
  385. // and if not it will create a new queue and set it to the required media id
  386. //
  387. WsbAffirmHr(FindRecallQueueElement(pSession, pMediaId, ppWorkQueue, bCreated));
  388. hr = (*ppWorkQueue)->Add(pFsaWorkItem,
  389. pBagId,
  390. dataSetStart);
  391. }WsbCatch( hr );
  392. LeaveCriticalSection(&m_WorkQueueLock);
  393. WsbTraceOut(OLESTR("CHsmTskMgr::AddToRecallQueueForFsaSession"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
  394. return(hr);
  395. }
  396. HRESULT
  397. CHsmTskMgr::IncreaseWorkQueueArraySize(
  398. ULONG numToAdd
  399. )
  400. {
  401. HRESULT hr = S_OK;
  402. ULONG memSize;
  403. LPVOID pTemp;
  404. //Begin Critical Section
  405. WsbTraceIn(OLESTR("CHsmTskMgr::IncreaseWorkQueueArraySize"),OLESTR("NumToAdd = %lu - Waiting for WorkQueueLock"), numToAdd);
  406. EnterCriticalSection(&m_WorkQueueLock);
  407. try {
  408. memSize = (m_NumWorkQueues + numToAdd) * sizeof(HSM_WORK_QUEUES);
  409. pTemp = WsbRealloc(m_pWorkQueues, memSize);
  410. WsbAffirm(0 != pTemp, E_FAIL);
  411. m_pWorkQueues = (HSM_WORK_QUEUES *) pTemp;
  412. ZeroMemory( (m_pWorkQueues + m_NumWorkQueues), (numToAdd * sizeof(HSM_WORK_QUEUES))
  413. );
  414. m_NumWorkQueues += numToAdd;
  415. }WsbCatch (hr);
  416. //End Critical Section
  417. LeaveCriticalSection(&m_WorkQueueLock);
  418. WsbTraceOut(OLESTR("CHsmTskMgr::IncreaseWorkQueueArraySize"),OLESTR("hr = <%ls>, QueuesInArray = <%lu>"),
  419. WsbHrAsString(hr), m_NumWorkQueues);
  420. return(hr);
  421. }
  422. HRESULT
  423. CHsmTskMgr::WorkQueueDone(
  424. IHsmSession *pSession,
  425. HSM_WORK_QUEUE_TYPE type,
  426. GUID *pMediaId
  427. )
  428. {
  429. HRESULT hr = S_OK;
  430. ULONG index;
  431. FILETIME dummyTime;
  432. IHsmRecallQueue *pRecallQueue;
  433. BOOL locked = FALSE;
  434. WsbTraceIn(OLESTR("CHsmTskMgr::WorkQueueDone"),OLESTR("type = %d"),
  435. static_cast<int>(type));
  436. try {
  437. EnterCriticalSection(&m_WorkQueueLock);
  438. locked = TRUE;
  439. //
  440. // Get the work queue index
  441. //
  442. hr = FindWorkQueueElement(pSession, type, &index, pMediaId);
  443. if (hr == S_OK) {
  444. WsbTrace(OLESTR("CHsmTskMgr::WorkQueueDone - ending queue # %lu\n"),
  445. index);
  446. ZeroMemory(&dummyTime, sizeof(FILETIME));
  447. if (type == HSM_WORK_TYPE_FSA_DEMAND_RECALL) {
  448. //
  449. // It is possible for recall queues that an element was added
  450. // just before we entered the critical section above
  451. //
  452. pRecallQueue = m_pWorkQueues[index].pRecallQueue;
  453. if (pRecallQueue->IsEmpty() == S_OK) {
  454. //
  455. // Ok to destroy the queue
  456. //
  457. WsbAffirmHr(SetRecallQueueElement(index, 0, HSM_WORK_TYPE_NONE, HSM_WORK_QUEUE_NONE, dummyTime));
  458. } else {
  459. //
  460. // We are not going to destroy the queue, since an element seems to have been added
  461. // before we locked the work queues
  462. //
  463. hr = S_FALSE;
  464. }
  465. } else {
  466. WsbAffirmHr(SetWorkQueueElement(index, 0, 0, HSM_WORK_TYPE_NONE, HSM_WORK_QUEUE_NONE, dummyTime));
  467. }
  468. LeaveCriticalSection(&m_WorkQueueLock);
  469. locked = FALSE;
  470. if (hr == S_OK) {
  471. // Reduce active count for this work queue type
  472. // It must protected from starting (activating) queues
  473. EnterCriticalSection(&m_CurrentRunningLock);
  474. for (ULONG i = 0; i < m_nWorkQueueTypes; i++) {
  475. if (type == m_pWorkQueueTypeInfo[i].Type) {
  476. if (m_pWorkQueueTypeInfo[i].NumActive > 0) {
  477. m_pWorkQueueTypeInfo[i].NumActive--;
  478. }
  479. break;
  480. }
  481. }
  482. LeaveCriticalSection(&m_CurrentRunningLock);
  483. }
  484. } else {
  485. LeaveCriticalSection(&m_WorkQueueLock);
  486. locked = FALSE;
  487. WsbAffirmHr(hr);
  488. }
  489. if (hr == S_OK) {
  490. //
  491. // If there are any queues waiting to start, start them
  492. //
  493. WsbAffirmHr(StartQueues());
  494. }
  495. }WsbCatchAndDo (hr,
  496. if (locked) {
  497. LeaveCriticalSection(&m_WorkQueueLock);
  498. locked = FALSE;
  499. }
  500. );
  501. WsbTraceOut(OLESTR("CHsmTskMgr::WorkQueueDone"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
  502. return(hr);
  503. }
  504. HRESULT
  505. CHsmTskMgr::AddWorkQueueElement(
  506. IHsmSession *pSession,
  507. HSM_WORK_QUEUE_TYPE type,
  508. ULONG *pIndex
  509. )
  510. {
  511. HRESULT hr = S_OK;
  512. BOOLEAN foundOne = FALSE;
  513. WsbTraceIn(OLESTR("CHsmTskMgr::AddWorkQueueElement"),
  514. OLESTR("type = %d, Waiting on WorkQueueLock"),
  515. static_cast<int>(type));
  516. //Begin Critical Section
  517. EnterCriticalSection(&m_WorkQueueLock);
  518. try {
  519. WsbAssert(0 != pIndex, E_POINTER);
  520. // Scan the array looking for an empty element
  521. for (ULONG i = 0; ((i < m_NumWorkQueues) && (foundOne == FALSE)); i++) {
  522. if (m_pWorkQueues[i].queueType == HSM_WORK_TYPE_NONE) {
  523. foundOne = TRUE;
  524. *pIndex = i;
  525. if (type != HSM_WORK_TYPE_FSA_DEMAND_RECALL) {
  526. //
  527. // Stow away the session. For recall queues, the session
  528. // is stored in the work item
  529. //
  530. m_pWorkQueues[i].pSession = pSession;
  531. }
  532. m_pWorkQueues[i].queueType = type;
  533. }
  534. }
  535. if (foundOne == FALSE) {
  536. // There are no empty elements so we need to add more
  537. *pIndex = m_NumWorkQueues;
  538. WsbAffirmHr(IncreaseWorkQueueArraySize(HsmWorkQueueArrayBumpSize));
  539. if (type != HSM_WORK_TYPE_FSA_DEMAND_RECALL) {
  540. //
  541. // We store the session in the work-queue element itself..
  542. // Just indicate this slot is taken..
  543. //
  544. m_pWorkQueues[*pIndex].pSession = pSession;
  545. }
  546. m_pWorkQueues[*pIndex].queueType = type;
  547. }
  548. }WsbCatch (hr);
  549. //End Critical Section
  550. LeaveCriticalSection(&m_WorkQueueLock);
  551. WsbTraceOut(OLESTR("CHsmTskMgr::AddWorkQueueElement"),
  552. OLESTR("hr = <%ls>, index = %lu"),WsbHrAsString(hr), *pIndex);
  553. return(hr);
  554. }
  555. HRESULT
  556. CHsmTskMgr::FindWorkQueueElement(
  557. IHsmSession *pSession,
  558. HSM_WORK_QUEUE_TYPE type,
  559. ULONG *pIndex,
  560. GUID *pMediaId
  561. )
  562. {
  563. HRESULT hr = S_OK;
  564. BOOLEAN foundOne = FALSE;
  565. GUID id;
  566. WsbTraceIn(OLESTR("CHsmTskMgr::FindWorkQueueElement"),
  567. OLESTR("type = %d, Waiting on WorkQueueLock"),
  568. static_cast<int>(type));
  569. //Begin Critical Section
  570. EnterCriticalSection(&m_WorkQueueLock);
  571. try {
  572. WsbAssert(0 != pIndex, E_POINTER);
  573. // Scan the array looking for an empty element
  574. for (ULONG i = 0; ((i < m_NumWorkQueues) && (foundOne == FALSE)); i++) {
  575. if (m_pWorkQueues[i].queueType == type) {
  576. if (type == HSM_WORK_TYPE_FSA_DEMAND_RECALL) {
  577. m_pWorkQueues[i].pRecallQueue->GetMediaId(&id);
  578. if (WsbCompareGuid(id, *pMediaId) != 0) {
  579. continue;
  580. }
  581. } else if (pSession != m_pWorkQueues[i].pSession) {
  582. continue;
  583. }
  584. foundOne = TRUE;
  585. *pIndex = i;
  586. }
  587. }
  588. if (FALSE == foundOne) {
  589. hr = WSB_E_NOTFOUND;
  590. }
  591. }WsbCatch (hr);
  592. //End Critical Section
  593. LeaveCriticalSection(&m_WorkQueueLock);
  594. WsbTraceOut(OLESTR("CHsmTskMgr::FindWorkQueueElement"),OLESTR("hr = <%ls>, index = <%ls>"),
  595. WsbHrAsString(hr), WsbPtrToUlongAsString(pIndex));
  596. return(hr);
  597. }
  598. HRESULT
  599. CHsmTskMgr::FindRecallQueueElement(
  600. IN IHsmSession *pSession,
  601. IN GUID *pMediaId,
  602. OUT IHsmRecallQueue **ppWorkQueue,
  603. OUT BOOL *bCreated
  604. )
  605. {
  606. HRESULT hr = S_OK;
  607. BOOLEAN foundOne = FALSE;
  608. GUID id;
  609. FILETIME birthDate;
  610. SYSTEMTIME systemTime;
  611. ULONG index=0;
  612. UNREFERENCED_PARAMETER(pSession);
  613. //
  614. // Important assumption: m_WorkQueueLock is held before calling this function
  615. //
  616. WsbTraceIn(OLESTR("CHsmTskMgr::FindRecallQueueElement"),
  617. OLESTR("Waiting on WorkQueueLock"));
  618. *bCreated = FALSE;
  619. try {
  620. for (ULONG i=0; (i < m_NumWorkQueues) && (foundOne == FALSE); i++) {
  621. //
  622. // Get the media id for the work queue
  623. //
  624. if (m_pWorkQueues[i].queueType == HSM_WORK_TYPE_FSA_DEMAND_RECALL) {
  625. if (m_pWorkQueues[i].pRecallQueue != NULL) {
  626. WsbAffirmHr(m_pWorkQueues[i].pRecallQueue->GetMediaId(&id));
  627. if ((WsbCompareGuid(id, *pMediaId) == 0)) {
  628. foundOne = TRUE;
  629. index = i;
  630. }
  631. }
  632. }
  633. }
  634. if (FALSE == foundOne) {
  635. //
  636. // No exisiting media queue was found. Make a new one
  637. //
  638. for (ULONG i = 0; ((i < m_NumWorkQueues) && (foundOne == FALSE)); i++) {
  639. if (m_pWorkQueues[i].queueType == HSM_WORK_TYPE_NONE) {
  640. foundOne = TRUE;
  641. index = i;
  642. }
  643. }
  644. if (foundOne == FALSE) {
  645. // There are no empty elements so we need to add more
  646. index = m_NumWorkQueues;
  647. WsbAffirmHr(IncreaseWorkQueueArraySize(HsmWorkQueueArrayBumpSize));
  648. }
  649. //
  650. // At this point we have the free slot index in index
  651. // The work queue has not been created so create it
  652. //
  653. WsbAffirmHr(m_pHsmServerCreate->CreateInstance(CLSID_CHsmRecallQueue, IID_IHsmRecallQueue,
  654. (void **)ppWorkQueue));
  655. WsbAffirmHr((*ppWorkQueue)->SetMediaId(pMediaId));
  656. WsbAffirmHr((*ppWorkQueue)->Init(m_pServer, (IHsmFsaTskMgr *)this));
  657. GetSystemTime(&systemTime);
  658. WsbAffirmStatus(SystemTimeToFileTime(&systemTime, &birthDate));
  659. m_pWorkQueues[index].queueType = HSM_WORK_TYPE_FSA_DEMAND_RECALL;
  660. m_pWorkQueues[index].pSession = NULL;
  661. m_pWorkQueues[index].pRecallQueue = *ppWorkQueue;
  662. m_pWorkQueues[index].queueState = HSM_WORK_QUEUE_IDLE;
  663. m_pWorkQueues[index].birthDate = birthDate;
  664. //
  665. // Indicate a new queue was created
  666. //
  667. *bCreated = TRUE;
  668. } else {
  669. //
  670. // Queue is already present, index points to it
  671. //
  672. *ppWorkQueue = m_pWorkQueues[index].pRecallQueue;
  673. if (0 != *ppWorkQueue) {
  674. //
  675. // We need to AddRef it..
  676. //
  677. (*ppWorkQueue)->AddRef();
  678. }
  679. }
  680. }WsbCatch (hr);
  681. WsbTraceOut(OLESTR("CHsmTskMgr::FindRecallQueueElement"),OLESTR("hr = <%ls>, index = <%ls>"),
  682. WsbHrAsString(hr), WsbLongAsString((LONG)index));
  683. return(hr);
  684. }
  685. HRESULT
  686. CHsmTskMgr::GetWorkQueueElement(
  687. ULONG index,
  688. IHsmSession **ppSession,
  689. IHsmWorkQueue **ppWorkQueue,
  690. HSM_WORK_QUEUE_TYPE *pType,
  691. HSM_WORK_QUEUE_STATE *pState,
  692. FILETIME *pBirthDate
  693. )
  694. {
  695. HRESULT hr = S_OK;
  696. WsbTraceIn(OLESTR("CHsmTskMgr::GetWorkQueueElement"),
  697. OLESTR("index = %lu, Waiting on WorkQueueLock"), index);
  698. //Begin Critical Section
  699. EnterCriticalSection(&m_WorkQueueLock);
  700. try {
  701. *pType = m_pWorkQueues[index].queueType;
  702. *ppSession = m_pWorkQueues[index].pSession;
  703. if (0 != *ppSession) {
  704. (*ppSession)->AddRef();
  705. }
  706. *ppWorkQueue = m_pWorkQueues[index].pWorkQueue;
  707. if (0 != *ppWorkQueue) {
  708. (*ppWorkQueue)->AddRef();
  709. }
  710. *pState = m_pWorkQueues[index].queueState;
  711. *pBirthDate = m_pWorkQueues[index].birthDate;
  712. }WsbCatch (hr);
  713. //End Critical Section
  714. LeaveCriticalSection(&m_WorkQueueLock);
  715. WsbTraceOut(OLESTR("CHsmTskMgr::GetWorkQueueElement"),
  716. OLESTR("hr = <%ls>, type = %d"),WsbHrAsString(hr),
  717. static_cast<int>(*pType));
  718. return(hr);
  719. }
  720. HRESULT
  721. CHsmTskMgr::GetRecallQueueElement(
  722. ULONG index,
  723. IHsmRecallQueue **ppWorkQueue,
  724. HSM_WORK_QUEUE_STATE *pState,
  725. FILETIME *pBirthDate
  726. )
  727. {
  728. HRESULT hr = S_OK;
  729. WsbTraceIn(OLESTR("CHsmTskMgr::GetRecallQueueElement"),
  730. OLESTR("index = %lu, Waiting on WorkQueueLock"), index);
  731. //Begin Critical Section
  732. EnterCriticalSection(&m_WorkQueueLock);
  733. try {
  734. WsbAffirm(m_pWorkQueues[index].queueType == HSM_WORK_TYPE_FSA_DEMAND_RECALL, E_INVALIDARG);
  735. *ppWorkQueue = m_pWorkQueues[index].pRecallQueue;
  736. if (0 != *ppWorkQueue) {
  737. (*ppWorkQueue)->AddRef();
  738. }
  739. *pState = m_pWorkQueues[index].queueState;
  740. *pBirthDate = m_pWorkQueues[index].birthDate;
  741. }WsbCatch (hr);
  742. //End Critical Section
  743. LeaveCriticalSection(&m_WorkQueueLock);
  744. WsbTraceOut(OLESTR("CHsmTskMgr::GetRecallQueueElement"),
  745. OLESTR("hr = <%ls>"),WsbHrAsString(hr));
  746. return(hr);
  747. }
  748. HRESULT
  749. CHsmTskMgr::SetWorkQueueElement(
  750. ULONG index,
  751. IHsmSession *pSession,
  752. IHsmWorkQueue *pWorkQueue,
  753. HSM_WORK_QUEUE_TYPE type,
  754. HSM_WORK_QUEUE_STATE state,
  755. FILETIME birthDate
  756. )
  757. {
  758. HRESULT hr = S_OK;
  759. WsbTraceIn(OLESTR("CHsmTskMgr::SetWorkQueueElement"),OLESTR("Waiting on WorkQueueLock"));
  760. //Begin Critical Section
  761. EnterCriticalSection(&m_WorkQueueLock);
  762. try {
  763. m_pWorkQueues[index].pSession = pSession;
  764. m_pWorkQueues[index].pWorkQueue = pWorkQueue;
  765. m_pWorkQueues[index].queueType = type;
  766. m_pWorkQueues[index].queueState = state;
  767. m_pWorkQueues[index].birthDate = birthDate;
  768. }WsbCatch (hr);
  769. //End Critical Section
  770. LeaveCriticalSection(&m_WorkQueueLock);
  771. WsbTraceOut(OLESTR("CHsmTskMgr::SetWorkQueueElement"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
  772. return(hr);
  773. }
  774. HRESULT
  775. CHsmTskMgr::SetRecallQueueElement(
  776. ULONG index,
  777. IHsmRecallQueue *pWorkQueue,
  778. HSM_WORK_QUEUE_TYPE queueType,
  779. HSM_WORK_QUEUE_STATE state,
  780. FILETIME birthDate
  781. )
  782. {
  783. HRESULT hr = S_OK;
  784. WsbTraceIn(OLESTR("CHsmTskMgr::SetWorkQueueElement"),OLESTR("Waiting on WorkQueueLock"));
  785. //Begin Critical Section
  786. EnterCriticalSection(&m_WorkQueueLock);
  787. try {
  788. WsbAffirm(m_pWorkQueues[index].queueType == HSM_WORK_TYPE_FSA_DEMAND_RECALL, E_INVALIDARG);
  789. //
  790. // Ensure the session pointer is empty, this is unused for recall queues
  791. //
  792. m_pWorkQueues[index].pSession = NULL;
  793. m_pWorkQueues[index].queueType = queueType;
  794. m_pWorkQueues[index].pRecallQueue = pWorkQueue;
  795. m_pWorkQueues[index].queueState = state;
  796. m_pWorkQueues[index].birthDate = birthDate;
  797. }WsbCatch (hr);
  798. //End Critical Section
  799. LeaveCriticalSection(&m_WorkQueueLock);
  800. WsbTraceOut(OLESTR("CHsmTskMgr::SetWorkQueueElement"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
  801. return(hr);
  802. }
  803. HRESULT
  804. CHsmTskMgr::RemoveWorkQueueElement(
  805. ULONG index
  806. )
  807. {
  808. HRESULT hr = S_OK;
  809. WsbTraceIn(OLESTR("CHsmTskMgr::RemoveWorkQueueElement"),OLESTR("Waiting on WorkQueueLock"));
  810. //Begin Critical Section
  811. EnterCriticalSection(&m_WorkQueueLock);
  812. try {
  813. m_pWorkQueues[index].pSession = 0;
  814. m_pWorkQueues[index].pWorkQueue = 0;
  815. m_pWorkQueues[index].queueType = HSM_WORK_TYPE_NONE;
  816. m_pWorkQueues[index].queueState = HSM_WORK_QUEUE_NONE;
  817. ZeroMemory(&(m_pWorkQueues[index].birthDate), sizeof(FILETIME));
  818. }WsbCatch (hr);
  819. //End Critical Section
  820. LeaveCriticalSection(&m_WorkQueueLock);
  821. WsbTraceOut(OLESTR("CHsmTskMgr::RemoveWorkQueueElement"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
  822. return(hr);
  823. }
  824. HRESULT
  825. CHsmTskMgr::StartQueues( void )
  826. {
  827. HRESULT hr = S_OK;
  828. ULONG uActive;
  829. WsbTraceIn(OLESTR("CHsmTskMgr::StartQueues"),OLESTR("Waiting on CurrentRunningLock"));
  830. //Begin Critical Section
  831. EnterCriticalSection(&m_CurrentRunningLock);
  832. try {
  833. // Go over work types, and start (activate) queues until the threshold
  834. // for the work type is reached
  835. for (ULONG i = 0; i < m_nWorkQueueTypes; i++) {
  836. // For Migrate queues, get the (dynamically set) Allowed limit
  837. if ((HSM_WORK_TYPE_FSA_MIGRATE == m_pWorkQueueTypeInfo[i].Type) ||
  838. (HSM_WORK_TYPE_FSA_DEMAND_RECALL == m_pWorkQueueTypeInfo[i].Type)) {
  839. WsbAffirmHr(m_pServer->GetCopyFilesLimit( &(m_pWorkQueueTypeInfo[i].MaxActiveAllowed) ));
  840. }
  841. WsbTrace(OLESTR("CHsmTskMgr::StartQueues: QueueType[%lu].NumActive = %lu, Allowed = %lu\n"),
  842. i, m_pWorkQueueTypeInfo[i].NumActive,
  843. m_pWorkQueueTypeInfo[i].MaxActiveAllowed);
  844. while ((uActive = m_pWorkQueueTypeInfo[i].NumActive) <
  845. m_pWorkQueueTypeInfo[i].MaxActiveAllowed) {
  846. WsbAffirmHr(StartFsaQueueType(m_pWorkQueueTypeInfo[i].Type));
  847. if (uActive == m_pWorkQueueTypeInfo[i].NumActive) {
  848. // no more work queues to activate - get out...
  849. break;
  850. }
  851. }
  852. }
  853. }WsbCatch (hr);
  854. //End Critical Section
  855. LeaveCriticalSection(&m_CurrentRunningLock);
  856. WsbTraceOut(OLESTR("CHsmTskMgr::StartQueues"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
  857. return(hr);
  858. }
  859. HRESULT
  860. CHsmTskMgr::StartFsaQueueType(HSM_WORK_QUEUE_TYPE type)
  861. {
  862. HRESULT hr = S_OK;
  863. CComPtr<IHsmWorkQueue> pWorkQueue;
  864. CComPtr<IHsmRecallQueue> pRecallQueue;
  865. ULONG index;
  866. WsbTraceIn(OLESTR("CHsmTskMgr::StartFsaQueueType"),OLESTR("type = %d"),
  867. static_cast<int>(type));
  868. try {
  869. // Find the oldest queue of this type
  870. hr = FindOldestQueue(type, &index);
  871. if (S_OK == hr) {
  872. HSM_WORK_QUEUE_STATE state;
  873. CComPtr<IHsmSession> l_pSession;
  874. HSM_WORK_QUEUE_TYPE l_type;
  875. FILETIME birthDate;
  876. // Make sure that the queue is idle
  877. if (type == HSM_WORK_TYPE_FSA_DEMAND_RECALL) {
  878. WsbAffirmHr(GetRecallQueueElement(index, &pRecallQueue, &state, &birthDate));
  879. } else {
  880. WsbAffirmHr(GetWorkQueueElement(index, &l_pSession, &pWorkQueue,
  881. &l_type, &state, &birthDate));
  882. }
  883. if (HSM_WORK_QUEUE_IDLE == state) {
  884. if (type == HSM_WORK_TYPE_FSA_DEMAND_RECALL) {
  885. WsbAffirmHr(SetRecallQueueElement(index, pRecallQueue,
  886. HSM_WORK_TYPE_FSA_DEMAND_RECALL,
  887. HSM_WORK_QUEUE_STARTING, birthDate));
  888. WsbAffirmHr(pRecallQueue->Start());
  889. WsbAffirmHr(SetRecallQueueElement(index, pRecallQueue,
  890. HSM_WORK_TYPE_FSA_DEMAND_RECALL,
  891. HSM_WORK_QUEUE_STARTED, birthDate));
  892. } else {
  893. WsbAffirmHr(SetWorkQueueElement(index, l_pSession, pWorkQueue,
  894. type, HSM_WORK_QUEUE_STARTING, birthDate));
  895. WsbAffirmHr(pWorkQueue->Start());
  896. WsbAffirmHr(SetWorkQueueElement(index, l_pSession, pWorkQueue,
  897. type, HSM_WORK_QUEUE_STARTED, birthDate));
  898. }
  899. WsbTrace(OLESTR("CHsmTskMgr::StartFsaQueueType - started work queue %lu\n"),
  900. index);
  901. // Increment active count for this work queue type
  902. for (ULONG i = 0; i < m_nWorkQueueTypes; i++) {
  903. if (type == m_pWorkQueueTypeInfo[i].Type) {
  904. m_pWorkQueueTypeInfo[i].NumActive++;
  905. break;
  906. }
  907. }
  908. }
  909. } else {
  910. if (WSB_E_NOTFOUND == hr) {
  911. hr = S_OK;
  912. }
  913. }
  914. WsbAffirmHr( hr );
  915. }WsbCatch (hr);
  916. WsbTraceOut(OLESTR("CHsmTskMgr::StartFsaQueueType"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
  917. return(hr);
  918. }
  919. HRESULT
  920. CHsmTskMgr::FindOldestQueue(
  921. HSM_WORK_QUEUE_TYPE type,
  922. ULONG *pIndex
  923. )
  924. {
  925. HRESULT hr = S_OK;
  926. FILETIME oldestOne;
  927. LONG compare;
  928. ULONG oldestIndex = 0xFFFFFFFF;
  929. BOOLEAN firstOne;
  930. WsbTraceIn(OLESTR("CHsmTskMgr::FindOldestQueue"),OLESTR("type = %d"),
  931. static_cast<int>(type));
  932. try {
  933. WsbAffirmPointer(pIndex);
  934. // Start out with the first time flag equal to TRUE so we select the first one with the right state and type
  935. firstOne = TRUE;
  936. for (ULONG i = 0; (i < m_NumWorkQueues); i++) {
  937. if ((type == m_pWorkQueues[i].queueType) && (HSM_WORK_QUEUE_IDLE == m_pWorkQueues[i].queueState)) {
  938. if (!firstOne)
  939. compare = CompareFileTime(&(m_pWorkQueues[i].birthDate), &(oldestOne));
  940. else
  941. compare = -1;
  942. if (compare < 0) {
  943. // found an older one
  944. firstOne = FALSE;
  945. oldestOne.dwLowDateTime = m_pWorkQueues[i].birthDate.dwLowDateTime;
  946. oldestOne.dwHighDateTime = m_pWorkQueues[i].birthDate.dwHighDateTime;
  947. oldestIndex = i;
  948. }
  949. }
  950. }
  951. if (0xFFFFFFFF == oldestIndex) {
  952. // Didn't find a match
  953. hr = WSB_E_NOTFOUND;
  954. } else {
  955. HSM_WORK_QUEUE_STATE state;
  956. CComPtr<IHsmSession> l_pSession;
  957. CComPtr<IHsmWorkQueue> l_pWorkQueue;
  958. CComPtr<IHsmRecallQueue> l_pRecallQueue;
  959. HSM_WORK_QUEUE_TYPE type2;
  960. FILETIME birthDate;
  961. // Make sure that the queue is idle
  962. if (type == HSM_WORK_TYPE_FSA_DEMAND_RECALL) {
  963. WsbAffirmHr(GetRecallQueueElement(oldestIndex, &l_pRecallQueue, &state, &birthDate));
  964. } else {
  965. WsbAffirmHr(GetWorkQueueElement(oldestIndex, &l_pSession, &l_pWorkQueue, &type2, &state, &birthDate));
  966. }
  967. if (HSM_WORK_QUEUE_IDLE == state) {
  968. *pIndex = oldestIndex;
  969. WsbTrace(OLESTR("CHsmTskMgr::FindOldestQueue: found index = %lu\n"),
  970. oldestIndex);
  971. } else {
  972. WsbTrace(OLESTR("CHsmTskMgr::FindOldestQueue - found NULL queue\n"));
  973. hr = WSB_E_NOTFOUND;
  974. }
  975. }
  976. }WsbCatch (hr);
  977. WsbTraceOut(OLESTR("CHsmTskMgr::FindOldestQueue"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
  978. return(hr);
  979. }
  980. HRESULT
  981. CHsmTskMgr::ChangeSysState(
  982. IN OUT HSM_SYSTEM_STATE* pSysState
  983. )
  984. /*++
  985. Implements:
  986. IHsmSystemState::ChangeSysState().
  987. --*/
  988. {
  989. HRESULT hr = S_OK;
  990. WsbTraceIn(OLESTR("CHsmTskMgr::ChangeSysState"), OLESTR(""));
  991. try {
  992. // Loop over work queues
  993. if (0 != m_pWorkQueues) {
  994. FILETIME dummyTime;
  995. ZeroMemory(&dummyTime, sizeof(FILETIME));
  996. for (ULONG i = 0; i < m_NumWorkQueues; i++) {
  997. if (m_pWorkQueues[i].pWorkQueue) {
  998. if (m_pWorkQueues[i].queueType == HSM_WORK_TYPE_FSA_DEMAND_RECALL) {
  999. if (pSysState->State & HSM_STATE_SHUTDOWN) {
  1000. m_pWorkQueues[i].pRecallQueue->Stop();
  1001. }
  1002. m_pWorkQueues[i].pRecallQueue->ChangeSysState(pSysState);
  1003. } else {
  1004. if (pSysState->State & HSM_STATE_SHUTDOWN) {
  1005. m_pWorkQueues[i].pWorkQueue->Stop();
  1006. }
  1007. m_pWorkQueues[i].pWorkQueue->ChangeSysState(pSysState);
  1008. }
  1009. }
  1010. if (pSysState->State & HSM_STATE_SHUTDOWN) {
  1011. hr = SetWorkQueueElement(i, 0, 0, HSM_WORK_TYPE_NONE, HSM_WORK_QUEUE_NONE, dummyTime);
  1012. }
  1013. }
  1014. }
  1015. }WsbCatch(hr);
  1016. WsbTraceOut(OLESTR("CHsmTskMgr::ChangeSysState"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1017. return(hr);
  1018. }
  1019. HRESULT
  1020. CHsmTskMgr::FindRecallMediaToUse(
  1021. IN IFsaPostIt *pFsaWorkItem,
  1022. OUT GUID *pMediaToUse,
  1023. OUT GUID *pBagId,
  1024. OUT LONGLONG *pDataSetStart
  1025. )
  1026. /*++
  1027. --*/
  1028. {
  1029. HRESULT hr = S_OK;
  1030. CComQIPtr<ISegDb, &IID_ISegDb> pSegDb;
  1031. CComPtr<IWsbDb> pWsbDb;
  1032. CComPtr<IWsbDbSession> pDbWorkSession;
  1033. BOOL openedDb = FALSE;
  1034. WsbTraceIn(OLESTR("CHsmTskMgr::FindRecallMediaToUse"),OLESTR(""));
  1035. try {
  1036. WsbAssert(pMediaToUse != 0, E_POINTER);
  1037. *pMediaToUse = GUID_NULL;
  1038. CComPtr<ISegRec> pSegRec;
  1039. GUID l_BagId;
  1040. LONGLONG l_FileStart;
  1041. LONGLONG l_FileSize;
  1042. USHORT l_SegFlags;
  1043. GUID l_PrimPos;
  1044. LONGLONG l_SecPos;
  1045. GUID storagePoolId;
  1046. FSA_PLACEHOLDER placeholder;
  1047. //
  1048. // Get the segment database
  1049. //
  1050. WsbAffirmHr(m_pServer->GetSegmentDb(&pWsbDb));
  1051. pSegDb = pWsbDb;
  1052. //
  1053. // Go to the segment database to find out where the data
  1054. // is located.
  1055. //
  1056. WsbAffirmHr(pFsaWorkItem->GetPlaceholder(&placeholder));
  1057. WsbAffirmHr(pFsaWorkItem->GetStoragePoolId(&storagePoolId));
  1058. WsbTrace(OLESTR("Finding SegmentRecord: <%ls>, <%ls>, <%ls>\n"),
  1059. WsbGuidAsString(placeholder.bagId),
  1060. WsbStringCopy(WsbLonglongAsString(placeholder.fileStart)),
  1061. WsbStringCopy(WsbLonglongAsString(placeholder.fileSize)));
  1062. WsbAffirmHr(pSegDb->Open(&pDbWorkSession));
  1063. openedDb = TRUE;
  1064. hr = pSegDb->SegFind(pDbWorkSession, placeholder.bagId, placeholder.fileStart,
  1065. placeholder.fileSize, &pSegRec);
  1066. if (S_OK != hr) {
  1067. //
  1068. // We couldn't find the segment record for this information!
  1069. //
  1070. hr = HSM_E_SEGMENT_INFO_NOT_FOUND;
  1071. WsbAffirmHr(hr);
  1072. }
  1073. WsbAffirmHr(pSegRec->GetSegmentRecord(&l_BagId, &l_FileStart, &l_FileSize, &l_SegFlags,
  1074. &l_PrimPos, &l_SecPos));
  1075. WsbAssert(0 != l_SecPos, HSM_E_BAD_SEGMENT_INFORMATION);
  1076. //
  1077. // In case of an indirect record, go to the dirtect record to get real location info
  1078. //
  1079. if (l_SegFlags & SEG_REC_INDIRECT_RECORD) {
  1080. pSegRec = 0;
  1081. WsbTrace(OLESTR("Finding indirect SegmentRecord: <%ls>, <%ls>, <%ls>\n"),
  1082. WsbGuidAsString(l_PrimPos), WsbStringCopy(WsbLonglongAsString(l_SecPos)),
  1083. WsbStringCopy(WsbLonglongAsString(placeholder.fileSize)));
  1084. hr = pSegDb->SegFind(pDbWorkSession, l_PrimPos, l_SecPos,
  1085. placeholder.fileSize, &pSegRec);
  1086. if (S_OK != hr) {
  1087. //
  1088. // We couldn't find the direct segment record for this segment!
  1089. //
  1090. hr = HSM_E_SEGMENT_INFO_NOT_FOUND;
  1091. WsbAffirmHr(hr);
  1092. }
  1093. WsbAffirmHr(pSegRec->GetSegmentRecord(&l_BagId, &l_FileStart, &l_FileSize, &l_SegFlags,
  1094. &l_PrimPos, &l_SecPos));
  1095. WsbAssert(0 != l_SecPos, HSM_E_BAD_SEGMENT_INFORMATION);
  1096. // Don't support a second indirection for now !!
  1097. WsbAssert(0 == (l_SegFlags & SEG_REC_INDIRECT_RECORD), HSM_E_BAD_SEGMENT_INFORMATION);
  1098. }
  1099. //
  1100. // Go to the media database to get the media ID
  1101. //
  1102. CComPtr<IMediaInfo> pMediaInfo;
  1103. GUID l_RmsMediaId;
  1104. WsbAffirmHr(pSegDb->GetEntity(pDbWorkSession, HSM_MEDIA_INFO_REC_TYPE, IID_IMediaInfo,
  1105. (void**)&pMediaInfo));
  1106. WsbAffirmHr(pMediaInfo->SetId(l_PrimPos));
  1107. hr = pMediaInfo->FindEQ();
  1108. if (S_OK != hr) {
  1109. hr = HSM_E_MEDIA_INFO_NOT_FOUND;
  1110. WsbAffirmHr(hr);
  1111. }
  1112. WsbAffirmHr(pMediaInfo->GetMediaSubsystemId(&l_RmsMediaId));
  1113. *pMediaToUse = l_RmsMediaId;
  1114. *pDataSetStart = l_SecPos;
  1115. *pBagId = l_BagId;
  1116. if (openedDb) {
  1117. pSegDb->Close(pDbWorkSession);
  1118. openedDb = FALSE;
  1119. }
  1120. }WsbCatchAndDo( hr,
  1121. if (openedDb){
  1122. pSegDb->Close(pDbWorkSession);}
  1123. ) ;
  1124. WsbTraceOut(OLESTR("CHsmTskMgr::FindRecallMediaToUse"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
  1125. return(hr);
  1126. }