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

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