1340 lines
38 KiB
C++
1340 lines
38 KiB
C++
|
/*++
|
|||
|
|
|||
|
<EFBFBD> 1998 Seagate Software, Inc. All rights reserved.
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
tskmgr.cpp
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This class represents the HSM task manager
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Cat Brant [cbrant] 6-Dec-1996
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
Incorporate demand recall queue support
|
|||
|
- Ravisankar Pudipeddi [ravisp] 1-Oct-199
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "stdafx.h"
|
|||
|
|
|||
|
#define WSB_TRACE_IS WSB_TRACE_BIT_HSMTSKMGR
|
|||
|
|
|||
|
#include "wsb.h"
|
|||
|
#include "hsmconn.h"
|
|||
|
#include "hsmeng.h"
|
|||
|
|
|||
|
#include "fsa.h"
|
|||
|
#include "task.h"
|
|||
|
#include "tskmgr.h"
|
|||
|
#include "hsmWorkQ.h"
|
|||
|
#include "engine.h"
|
|||
|
|
|||
|
#define MAX_WORK_QUEUE_TYPES 7
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmTskMgr::FinalConstruct(
|
|||
|
void
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This method does some initialization of the object that is necessary
|
|||
|
after construction.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
S_OK
|
|||
|
Anything returned by CWsbCollectable::FinalConstruct().
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CHsmTskMgr::FinalConstruct"),OLESTR(""));
|
|||
|
try {
|
|||
|
int index = 0;
|
|||
|
|
|||
|
WsbAssertHr(CComObjectRoot::FinalConstruct());
|
|||
|
m_pWorkQueues = 0;
|
|||
|
m_NumWorkQueues = 0;
|
|||
|
|
|||
|
// Set up queue type info and set limits
|
|||
|
m_nWorkQueueTypes = 0;
|
|||
|
m_pWorkQueueTypeInfo = static_cast<PHSM_WORK_QUEUE_TYPE_INFO>
|
|||
|
(WsbAlloc(MAX_WORK_QUEUE_TYPES *
|
|||
|
sizeof(HSM_WORK_QUEUE_TYPE_INFO)));
|
|||
|
WsbAffirmPointer(m_pWorkQueueTypeInfo);
|
|||
|
|
|||
|
// Migrate queues
|
|||
|
WsbAffirm(index < MAX_WORK_QUEUE_TYPES, WSB_E_INVALID_DATA);
|
|||
|
m_pWorkQueueTypeInfo[index].Type = HSM_WORK_TYPE_FSA_MIGRATE;
|
|||
|
m_pWorkQueueTypeInfo[index].MaxActiveAllowed = 1; // For Migrate, this is useless now
|
|||
|
// - the limit is dynamically set
|
|||
|
m_pWorkQueueTypeInfo[index].NumActive = 0;
|
|||
|
index++;
|
|||
|
|
|||
|
// Recall queues
|
|||
|
WsbAffirm(index < MAX_WORK_QUEUE_TYPES, WSB_E_INVALID_DATA);
|
|||
|
m_pWorkQueueTypeInfo[index].Type = HSM_WORK_TYPE_FSA_RECALL;
|
|||
|
m_pWorkQueueTypeInfo[index].MaxActiveAllowed = 1;
|
|||
|
m_pWorkQueueTypeInfo[index].NumActive = 0;
|
|||
|
index++;
|
|||
|
|
|||
|
// Demand Recall queues
|
|||
|
WsbAffirm(index < MAX_WORK_QUEUE_TYPES, WSB_E_INVALID_DATA);
|
|||
|
m_pWorkQueueTypeInfo[index].Type = HSM_WORK_TYPE_FSA_DEMAND_RECALL;
|
|||
|
//
|
|||
|
// MaxActiveAllowed is irrelevant for demand recall queues
|
|||
|
// as it is computed afresh
|
|||
|
//
|
|||
|
m_pWorkQueueTypeInfo[index].MaxActiveAllowed = 1;
|
|||
|
m_pWorkQueueTypeInfo[index].NumActive = 0;
|
|||
|
index++;
|
|||
|
|
|||
|
// Validate queues
|
|||
|
WsbAffirm(index < MAX_WORK_QUEUE_TYPES, WSB_E_INVALID_DATA);
|
|||
|
m_pWorkQueueTypeInfo[index].Type = HSM_WORK_TYPE_FSA_VALIDATE;
|
|||
|
m_pWorkQueueTypeInfo[index].MaxActiveAllowed = 2;
|
|||
|
m_pWorkQueueTypeInfo[index].NumActive = 0;
|
|||
|
index++;
|
|||
|
|
|||
|
|
|||
|
// Validate_for_truncate queues. MaxActiveAllowed is essentially
|
|||
|
// unlimited because this is the type of queue that the FSA's
|
|||
|
// auto-truncator creates. Because there is one queue for each managed
|
|||
|
// volume and these queues never go away, we can't limit the number
|
|||
|
// or we will create problems. The Truncate job also
|
|||
|
// creates this type of queue which means that type of job is not
|
|||
|
// limited by this mechanism, but that's the way it goes.
|
|||
|
WsbAffirm(index < MAX_WORK_QUEUE_TYPES, WSB_E_INVALID_DATA);
|
|||
|
m_pWorkQueueTypeInfo[index].Type = HSM_WORK_TYPE_FSA_VALIDATE_FOR_TRUNCATE;
|
|||
|
m_pWorkQueueTypeInfo[index].MaxActiveAllowed = 99999;
|
|||
|
m_pWorkQueueTypeInfo[index].NumActive = 0;
|
|||
|
index++;
|
|||
|
|
|||
|
m_nWorkQueueTypes = index;
|
|||
|
|
|||
|
}WsbCatch(hr);
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("CHsmTskMgr::FinalConstruct"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmTskMgr::FinalRelease(
|
|||
|
void
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This method does some clean up of the object that is necessary
|
|||
|
before destruction.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
S_OK
|
|||
|
Anything returned by CWsbCollection::FinalRelease().
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
HSM_SYSTEM_STATE SysState;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CHsmTskMgr::FinalRelease"),OLESTR(""));
|
|||
|
|
|||
|
SysState.State = HSM_STATE_SHUTDOWN;
|
|||
|
ChangeSysState(&SysState);
|
|||
|
|
|||
|
CComObjectRoot::FinalRelease();
|
|||
|
|
|||
|
// Free member resources
|
|||
|
if (0 != m_pWorkQueues) {
|
|||
|
WsbFree(m_pWorkQueues);
|
|||
|
m_pWorkQueues = NULL;
|
|||
|
}
|
|||
|
if (m_pWorkQueueTypeInfo) {
|
|||
|
WsbFree(m_pWorkQueueTypeInfo);
|
|||
|
m_pWorkQueueTypeInfo = NULL;
|
|||
|
}
|
|||
|
m_nWorkQueueTypes = 0;
|
|||
|
|
|||
|
DeleteCriticalSection(&m_WorkQueueLock);
|
|||
|
DeleteCriticalSection(&m_CurrentRunningLock);
|
|||
|
DeleteCriticalSection(&m_CreateWorkQueueLock);
|
|||
|
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("CHsmTskMgr::FinalRelease"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmTskMgr::Init(
|
|||
|
IUnknown *pServer
|
|||
|
)
|
|||
|
/*++
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This method does some initialization of the object that is necessary
|
|||
|
after construction.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
S_OK
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CHsmTskMgr::Init"),OLESTR(""));
|
|||
|
try {
|
|||
|
// Initialize critical sections
|
|||
|
InitializeCriticalSectionAndSpinCount (&m_WorkQueueLock, 1000);
|
|||
|
InitializeCriticalSectionAndSpinCount (&m_CurrentRunningLock, 1000);
|
|||
|
InitializeCriticalSectionAndSpinCount (&m_CreateWorkQueueLock, 1000);
|
|||
|
//
|
|||
|
// Get the server interface
|
|||
|
//
|
|||
|
WsbAffirmHr(pServer->QueryInterface(IID_IHsmServer, (void **)&m_pServer));
|
|||
|
//We want a weak link to the server so decrement the reference count
|
|||
|
m_pServer->Release();
|
|||
|
WsbAffirmHr(m_pServer->QueryInterface(IID_IWsbCreateLocalObject, (void **)&m_pHsmServerCreate));
|
|||
|
// We want a weak link to the server so decrement the reference count
|
|||
|
m_pHsmServerCreate->Release();
|
|||
|
|
|||
|
// Go ahead and preallocate some space for the work queues
|
|||
|
WsbAffirmHr(IncreaseWorkQueueArraySize(HsmWorkQueueArrayBumpSize));
|
|||
|
|
|||
|
}WsbCatch( hr );
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("CHsmTskMgr::Init"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
|||
|
return( hr );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmTskMgr::ContactOk(
|
|||
|
void
|
|||
|
)
|
|||
|
/*++
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This allows the caller to see if the RPC connection
|
|||
|
to the task manager is OK
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
S_OK
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
return( S_OK );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmTskMgr::DoFsaWork(
|
|||
|
IFsaPostIt *pFsaWorkItem
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Implements:
|
|||
|
|
|||
|
IHsmFsaTskMgr::DoFsaWork
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
CComPtr<IHsmSession> pSession;
|
|||
|
CComPtr<IHsmWorkQueue> pWorkQueue;
|
|||
|
CComPtr<IHsmRecallQueue> pRecallQueue;
|
|||
|
FSA_REQUEST_ACTION workAction;
|
|||
|
GUID mediaId;
|
|||
|
LONGLONG dataSetStart;
|
|||
|
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CHsmTskMgr::DoFsaWork"),OLESTR(""));
|
|||
|
try {
|
|||
|
CWsbStringPtr path;
|
|||
|
LONGLONG fileVersionId;
|
|||
|
FSA_PLACEHOLDER placeholder;
|
|||
|
GUID hsmId, bagId;
|
|||
|
BOOL bCreated;
|
|||
|
|
|||
|
// Get the version Id from the work Item.
|
|||
|
WsbAffirmHr(pFsaWorkItem->GetFileVersionId(&fileVersionId));
|
|||
|
|
|||
|
// Get the placeholder from the work item
|
|||
|
WsbAffirmHr(pFsaWorkItem->GetPlaceholder(&placeholder));
|
|||
|
|
|||
|
// Get the HSM ID from the server
|
|||
|
WsbAffirmHr(m_pServer->GetID(&hsmId));
|
|||
|
|
|||
|
//
|
|||
|
// Make sure this instance of the engine managed the file
|
|||
|
//
|
|||
|
if ((GUID_NULL != placeholder.hsmId) && (hsmId != placeholder.hsmId)) {
|
|||
|
CWsbStringPtr path;
|
|||
|
|
|||
|
(void)pFsaWorkItem->GetPath(&path, 0);
|
|||
|
hr = HSM_E_FILE_MANAGED_BY_DIFFERENT_HSM;
|
|||
|
WsbLogEvent(HSM_MESSAGE_FILE_MANAGED_BY_DIFFERENT_HSM, 0, NULL, WsbAbbreviatePath(path, 120), WsbHrAsString(hr), NULL);
|
|||
|
WsbThrow(hr);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Make sure there is a work allocater for this session
|
|||
|
//
|
|||
|
WsbAffirmHr(pFsaWorkItem->GetPath(&path, 0));
|
|||
|
WsbAffirmHr(pFsaWorkItem->GetSession(&pSession));
|
|||
|
WsbAffirmHr(pFsaWorkItem->GetRequestAction(&workAction));
|
|||
|
WsbTrace(OLESTR("CHsmTskMgr::DoFsaWork for <%ls> for <%lu>.\n"), (WCHAR *)path, workAction);
|
|||
|
|
|||
|
if ((workAction == FSA_REQUEST_ACTION_FILTER_RECALL) ||
|
|||
|
(workAction == FSA_REQUEST_ACTION_FILTER_READ)) {
|
|||
|
WsbAffirmHr(FindRecallMediaToUse(pFsaWorkItem, &mediaId, &bagId, &dataSetStart));
|
|||
|
WsbAffirmHr(AddToRecallQueueForFsaSession(pSession,&pRecallQueue, &bCreated, &mediaId, &bagId, dataSetStart, pFsaWorkItem));
|
|||
|
|
|||
|
} else {
|
|||
|
WsbAffirmHr(EnsureQueueForFsaSession(pSession, workAction, &pWorkQueue, &bCreated));
|
|||
|
//
|
|||
|
// Give the work to a queue
|
|||
|
//
|
|||
|
WsbAffirmHr(pWorkQueue->Add(pFsaWorkItem));
|
|||
|
}
|
|||
|
//
|
|||
|
// Start any queues that qualify (performance: only when a new queue is created)
|
|||
|
//
|
|||
|
if (bCreated) {
|
|||
|
WsbAffirmHr(StartQueues());
|
|||
|
}
|
|||
|
|
|||
|
}WsbCatch (hr);
|
|||
|
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("CHsmTskMgr::DoFsaWork"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmTskMgr::EnsureQueueForFsaSession(
|
|||
|
IN IHsmSession *pSession,
|
|||
|
IN FSA_REQUEST_ACTION fsaAction,
|
|||
|
OUT IHsmWorkQueue **ppWorkQueue,
|
|||
|
OUT BOOL *bCreated
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
HSM_WORK_QUEUE_STATE state;
|
|||
|
ULONG index;
|
|||
|
CComPtr<IHsmSession> l_pSession;
|
|||
|
HSM_WORK_QUEUE_TYPE type1=HSM_WORK_TYPE_NONE;
|
|||
|
HSM_WORK_QUEUE_TYPE type2;
|
|||
|
FILETIME birthDate;
|
|||
|
SYSTEMTIME systemTime;
|
|||
|
GUID sessionGuid;
|
|||
|
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CHsmTskMgr::EnsureQueueForFsaSession"),OLESTR("FsaRequestAction = <%lu>, Waiting on CreateWorkQueueLock"), fsaAction);
|
|||
|
EnterCriticalSection(&m_CreateWorkQueueLock);
|
|||
|
try {
|
|||
|
WsbAffirm(0 != ppWorkQueue, E_POINTER);
|
|||
|
// Convert FSA action to work queue type
|
|||
|
switch (fsaAction) {
|
|||
|
case FSA_REQUEST_ACTION_FILTER_READ:
|
|||
|
case FSA_REQUEST_ACTION_FILTER_RECALL:
|
|||
|
//
|
|||
|
// Should not happen!! AddToRecallQueueForFsaSession is the
|
|||
|
// right interface for recall items
|
|||
|
//
|
|||
|
WsbThrow(E_INVALIDARG);
|
|||
|
break;
|
|||
|
case FSA_REQUEST_ACTION_RECALL:
|
|||
|
type1 = HSM_WORK_TYPE_FSA_RECALL;
|
|||
|
break;
|
|||
|
case FSA_REQUEST_ACTION_PREMIGRATE:
|
|||
|
type1 = HSM_WORK_TYPE_FSA_MIGRATE;
|
|||
|
break;
|
|||
|
case FSA_REQUEST_ACTION_VALIDATE:
|
|||
|
type1 = HSM_WORK_TYPE_FSA_VALIDATE;
|
|||
|
break;
|
|||
|
case FSA_REQUEST_ACTION_VALIDATE_FOR_TRUNCATE:
|
|||
|
type1 = HSM_WORK_TYPE_FSA_VALIDATE_FOR_TRUNCATE;
|
|||
|
break;
|
|||
|
default:
|
|||
|
hr = E_NOTIMPL;
|
|||
|
type1 = HSM_WORK_TYPE_NONE;
|
|||
|
break;
|
|||
|
}
|
|||
|
WsbTrace(OLESTR("CHsmTskMgr::EnsureQueueForFsaSession: type1 = %d\n"),
|
|||
|
static_cast<int>(type1));
|
|||
|
|
|||
|
// Check the array of work queues and see if there is one for
|
|||
|
// this session.
|
|||
|
*bCreated = FALSE;
|
|||
|
hr = FindWorkQueueElement(pSession, type1, &index, NULL);
|
|||
|
if (hr == S_OK) {
|
|||
|
WsbAffirmHr(GetWorkQueueElement(index, &l_pSession, ppWorkQueue, &type2, &state, &birthDate));
|
|||
|
if ((l_pSession != pSession) || (type1 != type2)) {
|
|||
|
*ppWorkQueue = 0;
|
|||
|
WsbAssertHr(E_UNEXPECTED);
|
|||
|
}
|
|||
|
if (HSM_WORK_QUEUE_NONE == state) {
|
|||
|
WsbTrace(OLESTR("CHsmTskMgr::EnsureQueueForFsaSession: Creating new queue (state is NONE)\n"));
|
|||
|
WsbAffirmHr(m_pHsmServerCreate->CreateInstance(CLSID_CHsmWorkQueue, IID_IHsmWorkQueue,
|
|||
|
(void **)ppWorkQueue));
|
|||
|
WsbAffirmHr((*ppWorkQueue)->Init(m_pServer, pSession, (IHsmFsaTskMgr *)this, type1));
|
|||
|
GetSystemTime(&systemTime);
|
|||
|
WsbAffirmStatus(SystemTimeToFileTime(&systemTime, &birthDate));
|
|||
|
WsbAffirmHr(pSession->GetIdentifier(&sessionGuid));
|
|||
|
m_pWorkQueues[index].sessionId = sessionGuid;
|
|||
|
WsbAffirmHr(SetWorkQueueElement(index, pSession, *ppWorkQueue, type1, HSM_WORK_QUEUE_IDLE, birthDate));
|
|||
|
*bCreated = TRUE;
|
|||
|
}
|
|||
|
} else {
|
|||
|
if (hr == WSB_E_NOTFOUND) {
|
|||
|
hr = S_OK;
|
|||
|
WsbTrace(OLESTR("CHsmTskMgr::EnsureQueueForFsaSession: Creating new queue (queue not found)\n"));
|
|||
|
WsbAffirmHr(AddWorkQueueElement(pSession, type1, &index));
|
|||
|
// The work queue has not been created so create it
|
|||
|
WsbAffirmHr(m_pHsmServerCreate->CreateInstance(CLSID_CHsmWorkQueue, IID_IHsmWorkQueue,
|
|||
|
(void **)ppWorkQueue));
|
|||
|
WsbAffirmHr((*ppWorkQueue)->Init(m_pServer, pSession, (IHsmFsaTskMgr *)this, type1));
|
|||
|
GetSystemTime(&systemTime);
|
|||
|
WsbAffirmStatus(SystemTimeToFileTime(&systemTime, &birthDate));
|
|||
|
WsbAffirmHr(pSession->GetIdentifier(&sessionGuid));
|
|||
|
m_pWorkQueues[index].sessionId = sessionGuid;
|
|||
|
WsbAffirmHr(SetWorkQueueElement(index, pSession, *ppWorkQueue, type1, HSM_WORK_QUEUE_IDLE, birthDate));
|
|||
|
*bCreated = TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}WsbCatch( hr );
|
|||
|
|
|||
|
LeaveCriticalSection(&m_CreateWorkQueueLock);
|
|||
|
WsbTraceOut(OLESTR("CHsmTskMgr::EnsureQueueForFsaSession"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmTskMgr::AddToRecallQueueForFsaSession(
|
|||
|
IN IHsmSession *pSession,
|
|||
|
OUT IHsmRecallQueue **ppWorkQueue,
|
|||
|
OUT BOOL *bCreated,
|
|||
|
IN GUID *pMediaId,
|
|||
|
IN GUID *pBagId,
|
|||
|
IN LONGLONG dataSetStart,
|
|||
|
IN IFsaPostIt *pFsaWorkItem
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CHsmTskMgr::AddToRecallQueueForFsaSession"),OLESTR("Waiting on CreateWorkQueueLock"));
|
|||
|
|
|||
|
EnterCriticalSection(&m_WorkQueueLock);
|
|||
|
try {
|
|||
|
WsbAffirm(0 != ppWorkQueue, E_POINTER);
|
|||
|
//
|
|||
|
// This call will find the queue if it's already present -
|
|||
|
// and if not it will create a new queue and set it to the required media id
|
|||
|
//
|
|||
|
WsbAffirmHr(FindRecallQueueElement(pSession, pMediaId, ppWorkQueue, bCreated));
|
|||
|
hr = (*ppWorkQueue)->Add(pFsaWorkItem,
|
|||
|
pBagId,
|
|||
|
dataSetStart);
|
|||
|
|
|||
|
}WsbCatch( hr );
|
|||
|
|
|||
|
LeaveCriticalSection(&m_WorkQueueLock);
|
|||
|
WsbTraceOut(OLESTR("CHsmTskMgr::AddToRecallQueueForFsaSession"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmTskMgr::IncreaseWorkQueueArraySize(
|
|||
|
ULONG numToAdd
|
|||
|
)
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
ULONG memSize;
|
|||
|
LPVOID pTemp;
|
|||
|
|
|||
|
//Begin Critical Section
|
|||
|
WsbTraceIn(OLESTR("CHsmTskMgr::IncreaseWorkQueueArraySize"),OLESTR("NumToAdd = %lu - Waiting for WorkQueueLock"), numToAdd);
|
|||
|
EnterCriticalSection(&m_WorkQueueLock);
|
|||
|
try {
|
|||
|
memSize = (m_NumWorkQueues + numToAdd) * sizeof(HSM_WORK_QUEUES);
|
|||
|
pTemp = WsbRealloc(m_pWorkQueues, memSize);
|
|||
|
WsbAffirm(0 != pTemp, E_FAIL);
|
|||
|
m_pWorkQueues = (HSM_WORK_QUEUES *) pTemp;
|
|||
|
ZeroMemory( (m_pWorkQueues + m_NumWorkQueues), (numToAdd * sizeof(HSM_WORK_QUEUES))
|
|||
|
);
|
|||
|
m_NumWorkQueues += numToAdd;
|
|||
|
}WsbCatch (hr);
|
|||
|
|
|||
|
//End Critical Section
|
|||
|
LeaveCriticalSection(&m_WorkQueueLock);
|
|||
|
WsbTraceOut(OLESTR("CHsmTskMgr::IncreaseWorkQueueArraySize"),OLESTR("hr = <%ls>, QueuesInArray = <%lu>"),
|
|||
|
WsbHrAsString(hr), m_NumWorkQueues);
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmTskMgr::WorkQueueDone(
|
|||
|
IHsmSession *pSession,
|
|||
|
HSM_WORK_QUEUE_TYPE type,
|
|||
|
GUID *pMediaId
|
|||
|
)
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
ULONG index;
|
|||
|
FILETIME dummyTime;
|
|||
|
IHsmRecallQueue *pRecallQueue;
|
|||
|
BOOL locked = FALSE;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CHsmTskMgr::WorkQueueDone"),OLESTR("type = %d"),
|
|||
|
static_cast<int>(type));
|
|||
|
try {
|
|||
|
EnterCriticalSection(&m_WorkQueueLock);
|
|||
|
locked = TRUE;
|
|||
|
//
|
|||
|
// Get the work queue index
|
|||
|
//
|
|||
|
hr = FindWorkQueueElement(pSession, type, &index, pMediaId);
|
|||
|
if (hr == S_OK) {
|
|||
|
WsbTrace(OLESTR("CHsmTskMgr::WorkQueueDone - ending queue # %lu\n"),
|
|||
|
index);
|
|||
|
ZeroMemory(&dummyTime, sizeof(FILETIME));
|
|||
|
if (type == HSM_WORK_TYPE_FSA_DEMAND_RECALL) {
|
|||
|
//
|
|||
|
// It is possible for recall queues that an element was added
|
|||
|
// just before we entered the critical section above
|
|||
|
//
|
|||
|
pRecallQueue = m_pWorkQueues[index].pRecallQueue;
|
|||
|
if (pRecallQueue->IsEmpty() == S_OK) {
|
|||
|
//
|
|||
|
// Ok to destroy the queue
|
|||
|
//
|
|||
|
WsbAffirmHr(SetRecallQueueElement(index, 0, HSM_WORK_TYPE_NONE, HSM_WORK_QUEUE_NONE, dummyTime));
|
|||
|
} else {
|
|||
|
//
|
|||
|
// We are not going to destroy the queue, since an element seems to have been added
|
|||
|
// before we locked the work queues
|
|||
|
//
|
|||
|
hr = S_FALSE;
|
|||
|
}
|
|||
|
} else {
|
|||
|
WsbAffirmHr(SetWorkQueueElement(index, 0, 0, HSM_WORK_TYPE_NONE, HSM_WORK_QUEUE_NONE, dummyTime));
|
|||
|
}
|
|||
|
LeaveCriticalSection(&m_WorkQueueLock);
|
|||
|
locked = FALSE;
|
|||
|
|
|||
|
if (hr == S_OK) {
|
|||
|
// Reduce active count for this work queue type
|
|||
|
// It must protected from starting (activating) queues
|
|||
|
EnterCriticalSection(&m_CurrentRunningLock);
|
|||
|
for (ULONG i = 0; i < m_nWorkQueueTypes; i++) {
|
|||
|
if (type == m_pWorkQueueTypeInfo[i].Type) {
|
|||
|
if (m_pWorkQueueTypeInfo[i].NumActive > 0) {
|
|||
|
m_pWorkQueueTypeInfo[i].NumActive--;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
LeaveCriticalSection(&m_CurrentRunningLock);
|
|||
|
}
|
|||
|
} else {
|
|||
|
LeaveCriticalSection(&m_WorkQueueLock);
|
|||
|
locked = FALSE;
|
|||
|
WsbAffirmHr(hr);
|
|||
|
}
|
|||
|
|
|||
|
if (hr == S_OK) {
|
|||
|
//
|
|||
|
// If there are any queues waiting to start, start them
|
|||
|
//
|
|||
|
WsbAffirmHr(StartQueues());
|
|||
|
}
|
|||
|
}WsbCatchAndDo (hr,
|
|||
|
if (locked) {
|
|||
|
LeaveCriticalSection(&m_WorkQueueLock);
|
|||
|
locked = FALSE;
|
|||
|
}
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("CHsmTskMgr::WorkQueueDone"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmTskMgr::AddWorkQueueElement(
|
|||
|
IHsmSession *pSession,
|
|||
|
HSM_WORK_QUEUE_TYPE type,
|
|||
|
ULONG *pIndex
|
|||
|
)
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
BOOLEAN foundOne = FALSE;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CHsmTskMgr::AddWorkQueueElement"),
|
|||
|
OLESTR("type = %d, Waiting on WorkQueueLock"),
|
|||
|
static_cast<int>(type));
|
|||
|
|
|||
|
//Begin Critical Section
|
|||
|
EnterCriticalSection(&m_WorkQueueLock);
|
|||
|
|
|||
|
try {
|
|||
|
WsbAssert(0 != pIndex, E_POINTER);
|
|||
|
// Scan the array looking for an empty element
|
|||
|
for (ULONG i = 0; ((i < m_NumWorkQueues) && (foundOne == FALSE)); i++) {
|
|||
|
if (m_pWorkQueues[i].queueType == HSM_WORK_TYPE_NONE) {
|
|||
|
foundOne = TRUE;
|
|||
|
*pIndex = i;
|
|||
|
if (type != HSM_WORK_TYPE_FSA_DEMAND_RECALL) {
|
|||
|
//
|
|||
|
// Stow away the session. For recall queues, the session
|
|||
|
// is stored in the work item
|
|||
|
//
|
|||
|
m_pWorkQueues[i].pSession = pSession;
|
|||
|
}
|
|||
|
m_pWorkQueues[i].queueType = type;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (foundOne == FALSE) {
|
|||
|
// There are no empty elements so we need to add more
|
|||
|
*pIndex = m_NumWorkQueues;
|
|||
|
WsbAffirmHr(IncreaseWorkQueueArraySize(HsmWorkQueueArrayBumpSize));
|
|||
|
if (type != HSM_WORK_TYPE_FSA_DEMAND_RECALL) {
|
|||
|
//
|
|||
|
// We store the session in the work-queue element itself..
|
|||
|
// Just indicate this slot is taken..
|
|||
|
//
|
|||
|
m_pWorkQueues[*pIndex].pSession = pSession;
|
|||
|
}
|
|||
|
m_pWorkQueues[*pIndex].queueType = type;
|
|||
|
}
|
|||
|
|
|||
|
}WsbCatch (hr);
|
|||
|
|
|||
|
//End Critical Section
|
|||
|
LeaveCriticalSection(&m_WorkQueueLock);
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("CHsmTskMgr::AddWorkQueueElement"),
|
|||
|
OLESTR("hr = <%ls>, index = %lu"),WsbHrAsString(hr), *pIndex);
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmTskMgr::FindWorkQueueElement(
|
|||
|
IHsmSession *pSession,
|
|||
|
HSM_WORK_QUEUE_TYPE type,
|
|||
|
ULONG *pIndex,
|
|||
|
GUID *pMediaId
|
|||
|
)
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
BOOLEAN foundOne = FALSE;
|
|||
|
GUID id;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CHsmTskMgr::FindWorkQueueElement"),
|
|||
|
OLESTR("type = %d, Waiting on WorkQueueLock"),
|
|||
|
static_cast<int>(type));
|
|||
|
|
|||
|
//Begin Critical Section
|
|||
|
EnterCriticalSection(&m_WorkQueueLock);
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
WsbAssert(0 != pIndex, E_POINTER);
|
|||
|
|
|||
|
// Scan the array looking for an empty element
|
|||
|
for (ULONG i = 0; ((i < m_NumWorkQueues) && (foundOne == FALSE)); i++) {
|
|||
|
if (m_pWorkQueues[i].queueType == type) {
|
|||
|
if (type == HSM_WORK_TYPE_FSA_DEMAND_RECALL) {
|
|||
|
m_pWorkQueues[i].pRecallQueue->GetMediaId(&id);
|
|||
|
if (WsbCompareGuid(id, *pMediaId) != 0) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
} else if (pSession != m_pWorkQueues[i].pSession) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
foundOne = TRUE;
|
|||
|
*pIndex = i;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (FALSE == foundOne) {
|
|||
|
hr = WSB_E_NOTFOUND;
|
|||
|
}
|
|||
|
}WsbCatch (hr);
|
|||
|
//End Critical Section
|
|||
|
LeaveCriticalSection(&m_WorkQueueLock);
|
|||
|
WsbTraceOut(OLESTR("CHsmTskMgr::FindWorkQueueElement"),OLESTR("hr = <%ls>, index = <%ls>"),
|
|||
|
WsbHrAsString(hr), WsbPtrToUlongAsString(pIndex));
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmTskMgr::FindRecallQueueElement(
|
|||
|
IN IHsmSession *pSession,
|
|||
|
IN GUID *pMediaId,
|
|||
|
OUT IHsmRecallQueue **ppWorkQueue,
|
|||
|
OUT BOOL *bCreated
|
|||
|
)
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
BOOLEAN foundOne = FALSE;
|
|||
|
GUID id;
|
|||
|
FILETIME birthDate;
|
|||
|
SYSTEMTIME systemTime;
|
|||
|
ULONG index=0;
|
|||
|
|
|||
|
UNREFERENCED_PARAMETER(pSession);
|
|||
|
|
|||
|
//
|
|||
|
// Important assumption: m_WorkQueueLock is held before calling this function
|
|||
|
//
|
|||
|
WsbTraceIn(OLESTR("CHsmTskMgr::FindRecallQueueElement"),
|
|||
|
OLESTR("Waiting on WorkQueueLock"));
|
|||
|
|
|||
|
*bCreated = FALSE;
|
|||
|
|
|||
|
try {
|
|||
|
for (ULONG i=0; (i < m_NumWorkQueues) && (foundOne == FALSE); i++) {
|
|||
|
//
|
|||
|
// Get the media id for the work queue
|
|||
|
//
|
|||
|
if (m_pWorkQueues[i].queueType == HSM_WORK_TYPE_FSA_DEMAND_RECALL) {
|
|||
|
if (m_pWorkQueues[i].pRecallQueue != NULL) {
|
|||
|
WsbAffirmHr(m_pWorkQueues[i].pRecallQueue->GetMediaId(&id));
|
|||
|
if ((WsbCompareGuid(id, *pMediaId) == 0)) {
|
|||
|
foundOne = TRUE;
|
|||
|
index = i;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (FALSE == foundOne) {
|
|||
|
//
|
|||
|
// No exisiting media queue was found. Make a new one
|
|||
|
//
|
|||
|
for (ULONG i = 0; ((i < m_NumWorkQueues) && (foundOne == FALSE)); i++) {
|
|||
|
if (m_pWorkQueues[i].queueType == HSM_WORK_TYPE_NONE) {
|
|||
|
foundOne = TRUE;
|
|||
|
index = i;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (foundOne == FALSE) {
|
|||
|
// There are no empty elements so we need to add more
|
|||
|
index = m_NumWorkQueues;
|
|||
|
WsbAffirmHr(IncreaseWorkQueueArraySize(HsmWorkQueueArrayBumpSize));
|
|||
|
}
|
|||
|
//
|
|||
|
// At this point we have the free slot index in index
|
|||
|
// The work queue has not been created so create it
|
|||
|
//
|
|||
|
WsbAffirmHr(m_pHsmServerCreate->CreateInstance(CLSID_CHsmRecallQueue, IID_IHsmRecallQueue,
|
|||
|
(void **)ppWorkQueue));
|
|||
|
WsbAffirmHr((*ppWorkQueue)->SetMediaId(pMediaId));
|
|||
|
WsbAffirmHr((*ppWorkQueue)->Init(m_pServer, (IHsmFsaTskMgr *)this));
|
|||
|
GetSystemTime(&systemTime);
|
|||
|
WsbAffirmStatus(SystemTimeToFileTime(&systemTime, &birthDate));
|
|||
|
m_pWorkQueues[index].queueType = HSM_WORK_TYPE_FSA_DEMAND_RECALL;
|
|||
|
m_pWorkQueues[index].pSession = NULL;
|
|||
|
m_pWorkQueues[index].pRecallQueue = *ppWorkQueue;
|
|||
|
m_pWorkQueues[index].queueState = HSM_WORK_QUEUE_IDLE;
|
|||
|
m_pWorkQueues[index].birthDate = birthDate;
|
|||
|
//
|
|||
|
// Indicate a new queue was created
|
|||
|
//
|
|||
|
*bCreated = TRUE;
|
|||
|
} else {
|
|||
|
//
|
|||
|
// Queue is already present, index points to it
|
|||
|
//
|
|||
|
*ppWorkQueue = m_pWorkQueues[index].pRecallQueue;
|
|||
|
if (0 != *ppWorkQueue) {
|
|||
|
//
|
|||
|
// We need to AddRef it..
|
|||
|
//
|
|||
|
(*ppWorkQueue)->AddRef();
|
|||
|
}
|
|||
|
}
|
|||
|
}WsbCatch (hr);
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("CHsmTskMgr::FindRecallQueueElement"),OLESTR("hr = <%ls>, index = <%ls>"),
|
|||
|
WsbHrAsString(hr), WsbLongAsString((LONG)index));
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmTskMgr::GetWorkQueueElement(
|
|||
|
ULONG index,
|
|||
|
IHsmSession **ppSession,
|
|||
|
IHsmWorkQueue **ppWorkQueue,
|
|||
|
HSM_WORK_QUEUE_TYPE *pType,
|
|||
|
HSM_WORK_QUEUE_STATE *pState,
|
|||
|
FILETIME *pBirthDate
|
|||
|
)
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CHsmTskMgr::GetWorkQueueElement"),
|
|||
|
OLESTR("index = %lu, Waiting on WorkQueueLock"), index);
|
|||
|
//Begin Critical Section
|
|||
|
EnterCriticalSection(&m_WorkQueueLock);
|
|||
|
try {
|
|||
|
*pType = m_pWorkQueues[index].queueType;
|
|||
|
|
|||
|
*ppSession = m_pWorkQueues[index].pSession;
|
|||
|
if (0 != *ppSession) {
|
|||
|
(*ppSession)->AddRef();
|
|||
|
}
|
|||
|
|
|||
|
*ppWorkQueue = m_pWorkQueues[index].pWorkQueue;
|
|||
|
if (0 != *ppWorkQueue) {
|
|||
|
(*ppWorkQueue)->AddRef();
|
|||
|
}
|
|||
|
*pState = m_pWorkQueues[index].queueState;
|
|||
|
*pBirthDate = m_pWorkQueues[index].birthDate;
|
|||
|
|
|||
|
}WsbCatch (hr);
|
|||
|
|
|||
|
//End Critical Section
|
|||
|
LeaveCriticalSection(&m_WorkQueueLock);
|
|||
|
WsbTraceOut(OLESTR("CHsmTskMgr::GetWorkQueueElement"),
|
|||
|
OLESTR("hr = <%ls>, type = %d"),WsbHrAsString(hr),
|
|||
|
static_cast<int>(*pType));
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmTskMgr::GetRecallQueueElement(
|
|||
|
ULONG index,
|
|||
|
IHsmRecallQueue **ppWorkQueue,
|
|||
|
HSM_WORK_QUEUE_STATE *pState,
|
|||
|
FILETIME *pBirthDate
|
|||
|
)
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CHsmTskMgr::GetRecallQueueElement"),
|
|||
|
OLESTR("index = %lu, Waiting on WorkQueueLock"), index);
|
|||
|
//Begin Critical Section
|
|||
|
EnterCriticalSection(&m_WorkQueueLock);
|
|||
|
try {
|
|||
|
WsbAffirm(m_pWorkQueues[index].queueType == HSM_WORK_TYPE_FSA_DEMAND_RECALL, E_INVALIDARG);
|
|||
|
|
|||
|
*ppWorkQueue = m_pWorkQueues[index].pRecallQueue;
|
|||
|
if (0 != *ppWorkQueue) {
|
|||
|
(*ppWorkQueue)->AddRef();
|
|||
|
}
|
|||
|
*pState = m_pWorkQueues[index].queueState;
|
|||
|
*pBirthDate = m_pWorkQueues[index].birthDate;
|
|||
|
|
|||
|
}WsbCatch (hr);
|
|||
|
|
|||
|
//End Critical Section
|
|||
|
LeaveCriticalSection(&m_WorkQueueLock);
|
|||
|
WsbTraceOut(OLESTR("CHsmTskMgr::GetRecallQueueElement"),
|
|||
|
OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmTskMgr::SetWorkQueueElement(
|
|||
|
ULONG index,
|
|||
|
IHsmSession *pSession,
|
|||
|
IHsmWorkQueue *pWorkQueue,
|
|||
|
HSM_WORK_QUEUE_TYPE type,
|
|||
|
HSM_WORK_QUEUE_STATE state,
|
|||
|
FILETIME birthDate
|
|||
|
)
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CHsmTskMgr::SetWorkQueueElement"),OLESTR("Waiting on WorkQueueLock"));
|
|||
|
//Begin Critical Section
|
|||
|
EnterCriticalSection(&m_WorkQueueLock);
|
|||
|
try {
|
|||
|
m_pWorkQueues[index].pSession = pSession;
|
|||
|
m_pWorkQueues[index].pWorkQueue = pWorkQueue;
|
|||
|
m_pWorkQueues[index].queueType = type;
|
|||
|
m_pWorkQueues[index].queueState = state;
|
|||
|
m_pWorkQueues[index].birthDate = birthDate;
|
|||
|
|
|||
|
}WsbCatch (hr);
|
|||
|
|
|||
|
//End Critical Section
|
|||
|
LeaveCriticalSection(&m_WorkQueueLock);
|
|||
|
WsbTraceOut(OLESTR("CHsmTskMgr::SetWorkQueueElement"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmTskMgr::SetRecallQueueElement(
|
|||
|
ULONG index,
|
|||
|
IHsmRecallQueue *pWorkQueue,
|
|||
|
HSM_WORK_QUEUE_TYPE queueType,
|
|||
|
HSM_WORK_QUEUE_STATE state,
|
|||
|
FILETIME birthDate
|
|||
|
)
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CHsmTskMgr::SetWorkQueueElement"),OLESTR("Waiting on WorkQueueLock"));
|
|||
|
//Begin Critical Section
|
|||
|
EnterCriticalSection(&m_WorkQueueLock);
|
|||
|
try {
|
|||
|
WsbAffirm(m_pWorkQueues[index].queueType == HSM_WORK_TYPE_FSA_DEMAND_RECALL, E_INVALIDARG);
|
|||
|
//
|
|||
|
// Ensure the session pointer is empty, this is unused for recall queues
|
|||
|
//
|
|||
|
m_pWorkQueues[index].pSession = NULL;
|
|||
|
m_pWorkQueues[index].queueType = queueType;
|
|||
|
m_pWorkQueues[index].pRecallQueue = pWorkQueue;
|
|||
|
m_pWorkQueues[index].queueState = state;
|
|||
|
m_pWorkQueues[index].birthDate = birthDate;
|
|||
|
}WsbCatch (hr);
|
|||
|
|
|||
|
//End Critical Section
|
|||
|
LeaveCriticalSection(&m_WorkQueueLock);
|
|||
|
WsbTraceOut(OLESTR("CHsmTskMgr::SetWorkQueueElement"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmTskMgr::RemoveWorkQueueElement(
|
|||
|
ULONG index
|
|||
|
)
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CHsmTskMgr::RemoveWorkQueueElement"),OLESTR("Waiting on WorkQueueLock"));
|
|||
|
//Begin Critical Section
|
|||
|
EnterCriticalSection(&m_WorkQueueLock);
|
|||
|
try {
|
|||
|
m_pWorkQueues[index].pSession = 0;
|
|||
|
m_pWorkQueues[index].pWorkQueue = 0;
|
|||
|
m_pWorkQueues[index].queueType = HSM_WORK_TYPE_NONE;
|
|||
|
m_pWorkQueues[index].queueState = HSM_WORK_QUEUE_NONE;
|
|||
|
ZeroMemory(&(m_pWorkQueues[index].birthDate), sizeof(FILETIME));
|
|||
|
|
|||
|
}WsbCatch (hr);
|
|||
|
|
|||
|
//End Critical Section
|
|||
|
LeaveCriticalSection(&m_WorkQueueLock);
|
|||
|
WsbTraceOut(OLESTR("CHsmTskMgr::RemoveWorkQueueElement"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmTskMgr::StartQueues( void )
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
ULONG uActive;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CHsmTskMgr::StartQueues"),OLESTR("Waiting on CurrentRunningLock"));
|
|||
|
//Begin Critical Section
|
|||
|
EnterCriticalSection(&m_CurrentRunningLock);
|
|||
|
try {
|
|||
|
// Go over work types, and start (activate) queues until the threshold
|
|||
|
// for the work type is reached
|
|||
|
for (ULONG i = 0; i < m_nWorkQueueTypes; i++) {
|
|||
|
// For Migrate queues, get the (dynamically set) Allowed limit
|
|||
|
if ((HSM_WORK_TYPE_FSA_MIGRATE == m_pWorkQueueTypeInfo[i].Type) ||
|
|||
|
(HSM_WORK_TYPE_FSA_DEMAND_RECALL == m_pWorkQueueTypeInfo[i].Type)) {
|
|||
|
WsbAffirmHr(m_pServer->GetCopyFilesLimit( &(m_pWorkQueueTypeInfo[i].MaxActiveAllowed) ));
|
|||
|
}
|
|||
|
|
|||
|
WsbTrace(OLESTR("CHsmTskMgr::StartQueues: QueueType[%lu].NumActive = %lu, Allowed = %lu\n"),
|
|||
|
i, m_pWorkQueueTypeInfo[i].NumActive,
|
|||
|
m_pWorkQueueTypeInfo[i].MaxActiveAllowed);
|
|||
|
while ((uActive = m_pWorkQueueTypeInfo[i].NumActive) <
|
|||
|
m_pWorkQueueTypeInfo[i].MaxActiveAllowed) {
|
|||
|
WsbAffirmHr(StartFsaQueueType(m_pWorkQueueTypeInfo[i].Type));
|
|||
|
if (uActive == m_pWorkQueueTypeInfo[i].NumActive) {
|
|||
|
// no more work queues to activate - get out...
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}WsbCatch (hr);
|
|||
|
|
|||
|
//End Critical Section
|
|||
|
LeaveCriticalSection(&m_CurrentRunningLock);
|
|||
|
WsbTraceOut(OLESTR("CHsmTskMgr::StartQueues"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmTskMgr::StartFsaQueueType(HSM_WORK_QUEUE_TYPE type)
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
CComPtr<IHsmWorkQueue> pWorkQueue;
|
|||
|
CComPtr<IHsmRecallQueue> pRecallQueue;
|
|||
|
ULONG index;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CHsmTskMgr::StartFsaQueueType"),OLESTR("type = %d"),
|
|||
|
static_cast<int>(type));
|
|||
|
try {
|
|||
|
// Find the oldest queue of this type
|
|||
|
hr = FindOldestQueue(type, &index);
|
|||
|
if (S_OK == hr) {
|
|||
|
HSM_WORK_QUEUE_STATE state;
|
|||
|
CComPtr<IHsmSession> l_pSession;
|
|||
|
HSM_WORK_QUEUE_TYPE l_type;
|
|||
|
FILETIME birthDate;
|
|||
|
|
|||
|
// Make sure that the queue is idle
|
|||
|
if (type == HSM_WORK_TYPE_FSA_DEMAND_RECALL) {
|
|||
|
WsbAffirmHr(GetRecallQueueElement(index, &pRecallQueue, &state, &birthDate));
|
|||
|
} else {
|
|||
|
WsbAffirmHr(GetWorkQueueElement(index, &l_pSession, &pWorkQueue,
|
|||
|
&l_type, &state, &birthDate));
|
|||
|
}
|
|||
|
if (HSM_WORK_QUEUE_IDLE == state) {
|
|||
|
if (type == HSM_WORK_TYPE_FSA_DEMAND_RECALL) {
|
|||
|
WsbAffirmHr(SetRecallQueueElement(index, pRecallQueue,
|
|||
|
HSM_WORK_TYPE_FSA_DEMAND_RECALL,
|
|||
|
HSM_WORK_QUEUE_STARTING, birthDate));
|
|||
|
WsbAffirmHr(pRecallQueue->Start());
|
|||
|
WsbAffirmHr(SetRecallQueueElement(index, pRecallQueue,
|
|||
|
HSM_WORK_TYPE_FSA_DEMAND_RECALL,
|
|||
|
HSM_WORK_QUEUE_STARTED, birthDate));
|
|||
|
} else {
|
|||
|
WsbAffirmHr(SetWorkQueueElement(index, l_pSession, pWorkQueue,
|
|||
|
type, HSM_WORK_QUEUE_STARTING, birthDate));
|
|||
|
WsbAffirmHr(pWorkQueue->Start());
|
|||
|
WsbAffirmHr(SetWorkQueueElement(index, l_pSession, pWorkQueue,
|
|||
|
type, HSM_WORK_QUEUE_STARTED, birthDate));
|
|||
|
}
|
|||
|
WsbTrace(OLESTR("CHsmTskMgr::StartFsaQueueType - started work queue %lu\n"),
|
|||
|
index);
|
|||
|
|
|||
|
|
|||
|
// Increment active count for this work queue type
|
|||
|
for (ULONG i = 0; i < m_nWorkQueueTypes; i++) {
|
|||
|
if (type == m_pWorkQueueTypeInfo[i].Type) {
|
|||
|
m_pWorkQueueTypeInfo[i].NumActive++;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
if (WSB_E_NOTFOUND == hr) {
|
|||
|
hr = S_OK;
|
|||
|
}
|
|||
|
}
|
|||
|
WsbAffirmHr( hr );
|
|||
|
|
|||
|
}WsbCatch (hr);
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("CHsmTskMgr::StartFsaQueueType"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmTskMgr::FindOldestQueue(
|
|||
|
HSM_WORK_QUEUE_TYPE type,
|
|||
|
ULONG *pIndex
|
|||
|
)
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
FILETIME oldestOne;
|
|||
|
LONG compare;
|
|||
|
ULONG oldestIndex = 0xFFFFFFFF;
|
|||
|
BOOLEAN firstOne;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CHsmTskMgr::FindOldestQueue"),OLESTR("type = %d"),
|
|||
|
static_cast<int>(type));
|
|||
|
try {
|
|||
|
WsbAffirmPointer(pIndex);
|
|||
|
|
|||
|
// Start out with the first time flag equal to TRUE so we select the first one with the right state and type
|
|||
|
firstOne = TRUE;
|
|||
|
|
|||
|
for (ULONG i = 0; (i < m_NumWorkQueues); i++) {
|
|||
|
if ((type == m_pWorkQueues[i].queueType) && (HSM_WORK_QUEUE_IDLE == m_pWorkQueues[i].queueState)) {
|
|||
|
if (!firstOne)
|
|||
|
compare = CompareFileTime(&(m_pWorkQueues[i].birthDate), &(oldestOne));
|
|||
|
else
|
|||
|
compare = -1;
|
|||
|
if (compare < 0) {
|
|||
|
// found an older one
|
|||
|
firstOne = FALSE;
|
|||
|
oldestOne.dwLowDateTime = m_pWorkQueues[i].birthDate.dwLowDateTime;
|
|||
|
oldestOne.dwHighDateTime = m_pWorkQueues[i].birthDate.dwHighDateTime;
|
|||
|
oldestIndex = i;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (0xFFFFFFFF == oldestIndex) {
|
|||
|
// Didn't find a match
|
|||
|
hr = WSB_E_NOTFOUND;
|
|||
|
} else {
|
|||
|
HSM_WORK_QUEUE_STATE state;
|
|||
|
CComPtr<IHsmSession> l_pSession;
|
|||
|
CComPtr<IHsmWorkQueue> l_pWorkQueue;
|
|||
|
CComPtr<IHsmRecallQueue> l_pRecallQueue;
|
|||
|
HSM_WORK_QUEUE_TYPE type2;
|
|||
|
FILETIME birthDate;
|
|||
|
|
|||
|
// Make sure that the queue is idle
|
|||
|
if (type == HSM_WORK_TYPE_FSA_DEMAND_RECALL) {
|
|||
|
WsbAffirmHr(GetRecallQueueElement(oldestIndex, &l_pRecallQueue, &state, &birthDate));
|
|||
|
} else {
|
|||
|
WsbAffirmHr(GetWorkQueueElement(oldestIndex, &l_pSession, &l_pWorkQueue, &type2, &state, &birthDate));
|
|||
|
}
|
|||
|
if (HSM_WORK_QUEUE_IDLE == state) {
|
|||
|
*pIndex = oldestIndex;
|
|||
|
WsbTrace(OLESTR("CHsmTskMgr::FindOldestQueue: found index = %lu\n"),
|
|||
|
oldestIndex);
|
|||
|
} else {
|
|||
|
WsbTrace(OLESTR("CHsmTskMgr::FindOldestQueue - found NULL queue\n"));
|
|||
|
hr = WSB_E_NOTFOUND;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}WsbCatch (hr);
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("CHsmTskMgr::FindOldestQueue"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmTskMgr::ChangeSysState(
|
|||
|
IN OUT HSM_SYSTEM_STATE* pSysState
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Implements:
|
|||
|
|
|||
|
IHsmSystemState::ChangeSysState().
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CHsmTskMgr::ChangeSysState"), OLESTR(""));
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
// Loop over work queues
|
|||
|
if (0 != m_pWorkQueues) {
|
|||
|
FILETIME dummyTime;
|
|||
|
ZeroMemory(&dummyTime, sizeof(FILETIME));
|
|||
|
for (ULONG i = 0; i < m_NumWorkQueues; i++) {
|
|||
|
if (m_pWorkQueues[i].pWorkQueue) {
|
|||
|
|
|||
|
if (m_pWorkQueues[i].queueType == HSM_WORK_TYPE_FSA_DEMAND_RECALL) {
|
|||
|
if (pSysState->State & HSM_STATE_SHUTDOWN) {
|
|||
|
m_pWorkQueues[i].pRecallQueue->Stop();
|
|||
|
}
|
|||
|
m_pWorkQueues[i].pRecallQueue->ChangeSysState(pSysState);
|
|||
|
} else {
|
|||
|
if (pSysState->State & HSM_STATE_SHUTDOWN) {
|
|||
|
m_pWorkQueues[i].pWorkQueue->Stop();
|
|||
|
}
|
|||
|
m_pWorkQueues[i].pWorkQueue->ChangeSysState(pSysState);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (pSysState->State & HSM_STATE_SHUTDOWN) {
|
|||
|
hr = SetWorkQueueElement(i, 0, 0, HSM_WORK_TYPE_NONE, HSM_WORK_QUEUE_NONE, dummyTime);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}WsbCatch(hr);
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("CHsmTskMgr::ChangeSysState"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|||
|
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmTskMgr::FindRecallMediaToUse(
|
|||
|
IN IFsaPostIt *pFsaWorkItem,
|
|||
|
OUT GUID *pMediaToUse,
|
|||
|
OUT GUID *pBagId,
|
|||
|
OUT LONGLONG *pDataSetStart
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
CComQIPtr<ISegDb, &IID_ISegDb> pSegDb;
|
|||
|
CComPtr<IWsbDb> pWsbDb;
|
|||
|
CComPtr<IWsbDbSession> pDbWorkSession;
|
|||
|
BOOL openedDb = FALSE;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CHsmTskMgr::FindRecallMediaToUse"),OLESTR(""));
|
|||
|
try {
|
|||
|
WsbAssert(pMediaToUse != 0, E_POINTER);
|
|||
|
*pMediaToUse = GUID_NULL;
|
|||
|
|
|||
|
CComPtr<ISegRec> pSegRec;
|
|||
|
GUID l_BagId;
|
|||
|
LONGLONG l_FileStart;
|
|||
|
LONGLONG l_FileSize;
|
|||
|
USHORT l_SegFlags;
|
|||
|
GUID l_PrimPos;
|
|||
|
LONGLONG l_SecPos;
|
|||
|
GUID storagePoolId;
|
|||
|
FSA_PLACEHOLDER placeholder;
|
|||
|
|
|||
|
//
|
|||
|
// Get the segment database
|
|||
|
//
|
|||
|
WsbAffirmHr(m_pServer->GetSegmentDb(&pWsbDb));
|
|||
|
pSegDb = pWsbDb;
|
|||
|
//
|
|||
|
// Go to the segment database to find out where the data
|
|||
|
// is located.
|
|||
|
//
|
|||
|
WsbAffirmHr(pFsaWorkItem->GetPlaceholder(&placeholder));
|
|||
|
WsbAffirmHr(pFsaWorkItem->GetStoragePoolId(&storagePoolId));
|
|||
|
|
|||
|
WsbTrace(OLESTR("Finding SegmentRecord: <%ls>, <%ls>, <%ls>\n"),
|
|||
|
WsbGuidAsString(placeholder.bagId),
|
|||
|
WsbStringCopy(WsbLonglongAsString(placeholder.fileStart)),
|
|||
|
WsbStringCopy(WsbLonglongAsString(placeholder.fileSize)));
|
|||
|
|
|||
|
WsbAffirmHr(pSegDb->Open(&pDbWorkSession));
|
|||
|
openedDb = TRUE;
|
|||
|
hr = pSegDb->SegFind(pDbWorkSession, placeholder.bagId, placeholder.fileStart,
|
|||
|
placeholder.fileSize, &pSegRec);
|
|||
|
if (S_OK != hr) {
|
|||
|
//
|
|||
|
// We couldn't find the segment record for this information!
|
|||
|
//
|
|||
|
hr = HSM_E_SEGMENT_INFO_NOT_FOUND;
|
|||
|
WsbAffirmHr(hr);
|
|||
|
}
|
|||
|
WsbAffirmHr(pSegRec->GetSegmentRecord(&l_BagId, &l_FileStart, &l_FileSize, &l_SegFlags,
|
|||
|
&l_PrimPos, &l_SecPos));
|
|||
|
WsbAssert(0 != l_SecPos, HSM_E_BAD_SEGMENT_INFORMATION);
|
|||
|
|
|||
|
//
|
|||
|
// In case of an indirect record, go to the dirtect record to get real location info
|
|||
|
//
|
|||
|
if (l_SegFlags & SEG_REC_INDIRECT_RECORD) {
|
|||
|
pSegRec = 0;
|
|||
|
|
|||
|
WsbTrace(OLESTR("Finding indirect SegmentRecord: <%ls>, <%ls>, <%ls>\n"),
|
|||
|
WsbGuidAsString(l_PrimPos), WsbStringCopy(WsbLonglongAsString(l_SecPos)),
|
|||
|
WsbStringCopy(WsbLonglongAsString(placeholder.fileSize)));
|
|||
|
|
|||
|
hr = pSegDb->SegFind(pDbWorkSession, l_PrimPos, l_SecPos,
|
|||
|
placeholder.fileSize, &pSegRec);
|
|||
|
if (S_OK != hr) {
|
|||
|
//
|
|||
|
// We couldn't find the direct segment record for this segment!
|
|||
|
//
|
|||
|
hr = HSM_E_SEGMENT_INFO_NOT_FOUND;
|
|||
|
WsbAffirmHr(hr);
|
|||
|
}
|
|||
|
|
|||
|
WsbAffirmHr(pSegRec->GetSegmentRecord(&l_BagId, &l_FileStart, &l_FileSize, &l_SegFlags,
|
|||
|
&l_PrimPos, &l_SecPos));
|
|||
|
WsbAssert(0 != l_SecPos, HSM_E_BAD_SEGMENT_INFORMATION);
|
|||
|
|
|||
|
// Don't support a second indirection for now !!
|
|||
|
WsbAssert(0 == (l_SegFlags & SEG_REC_INDIRECT_RECORD), HSM_E_BAD_SEGMENT_INFORMATION);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Go to the media database to get the media ID
|
|||
|
//
|
|||
|
CComPtr<IMediaInfo> pMediaInfo;
|
|||
|
GUID l_RmsMediaId;
|
|||
|
|
|||
|
WsbAffirmHr(pSegDb->GetEntity(pDbWorkSession, HSM_MEDIA_INFO_REC_TYPE, IID_IMediaInfo,
|
|||
|
(void**)&pMediaInfo));
|
|||
|
WsbAffirmHr(pMediaInfo->SetId(l_PrimPos));
|
|||
|
hr = pMediaInfo->FindEQ();
|
|||
|
if (S_OK != hr) {
|
|||
|
hr = HSM_E_MEDIA_INFO_NOT_FOUND;
|
|||
|
WsbAffirmHr(hr);
|
|||
|
}
|
|||
|
WsbAffirmHr(pMediaInfo->GetMediaSubsystemId(&l_RmsMediaId));
|
|||
|
*pMediaToUse = l_RmsMediaId;
|
|||
|
*pDataSetStart = l_SecPos;
|
|||
|
*pBagId = l_BagId;
|
|||
|
if (openedDb) {
|
|||
|
pSegDb->Close(pDbWorkSession);
|
|||
|
openedDb = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
}WsbCatchAndDo( hr,
|
|||
|
if (openedDb){
|
|||
|
pSegDb->Close(pDbWorkSession);}
|
|||
|
) ;
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("CHsmTskMgr::FindRecallMediaToUse"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
|||
|
return(hr);
|
|||
|
}
|