2417 lines
74 KiB
C++
2417 lines
74 KiB
C++
/*++
|
||
|
||
|
||
Module Name:
|
||
|
||
hsmreclq.cpp
|
||
|
||
Abstract:
|
||
|
||
This class represents the HSM Demand Recall Queue manager
|
||
It handles recalls initiated by users accessing HSM managed
|
||
files. Based on the regular HSM queue manager (CHsmWorkQueue)
|
||
|
||
Author:
|
||
|
||
Ravisankar Pudipeddi [ravisp] 1 Oct. 1999
|
||
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "stdafx.h"
|
||
|
||
#define WSB_TRACE_IS WSB_TRACE_BIT_HSMTSKMGR
|
||
static USHORT iCount = 0;
|
||
|
||
#include "fsa.h"
|
||
#include "rms.h"
|
||
#include "metadef.h"
|
||
#include "jobint.h"
|
||
#include "hsmconn.h"
|
||
#include "wsb.h"
|
||
#include "hsmeng.h"
|
||
#include "mover.h"
|
||
#include "hsmreclq.h"
|
||
|
||
#include "engine.h"
|
||
#include "task.h"
|
||
#include "tskmgr.h"
|
||
#include "segdb.h"
|
||
|
||
#define STRINGIZE(_str) (OLESTR( #_str ))
|
||
#define RETURN_STRINGIZED_CASE(_case) \
|
||
case _case: \
|
||
return ( STRINGIZE( _case ) );
|
||
|
||
// Local prototypes
|
||
DWORD HsmRecallQueueThread(void *pVoid);
|
||
static const OLECHAR * JobStateAsString (HSM_JOB_STATE state);
|
||
|
||
static const OLECHAR *
|
||
JobStateAsString (
|
||
IN HSM_JOB_STATE state
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Gives back a static string representing the connection state.
|
||
|
||
Arguments:
|
||
|
||
state - the state to return a string for.
|
||
|
||
Return Value:
|
||
|
||
NULL - invalid state passed in.
|
||
|
||
Otherwise, a valid char *.
|
||
|
||
--*/
|
||
{
|
||
//
|
||
// Do the Switch
|
||
//
|
||
|
||
switch (state) {
|
||
|
||
RETURN_STRINGIZED_CASE( HSM_JOB_STATE_ACTIVE );
|
||
RETURN_STRINGIZED_CASE( HSM_JOB_STATE_CANCELLED );
|
||
RETURN_STRINGIZED_CASE( HSM_JOB_STATE_CANCELLING );
|
||
RETURN_STRINGIZED_CASE( HSM_JOB_STATE_DONE );
|
||
RETURN_STRINGIZED_CASE( HSM_JOB_STATE_FAILED );
|
||
RETURN_STRINGIZED_CASE( HSM_JOB_STATE_IDLE );
|
||
RETURN_STRINGIZED_CASE( HSM_JOB_STATE_PAUSED );
|
||
RETURN_STRINGIZED_CASE( HSM_JOB_STATE_PAUSING );
|
||
RETURN_STRINGIZED_CASE( HSM_JOB_STATE_RESUMING );
|
||
RETURN_STRINGIZED_CASE( HSM_JOB_STATE_SKIPPED );
|
||
RETURN_STRINGIZED_CASE( HSM_JOB_STATE_STARTING );
|
||
RETURN_STRINGIZED_CASE( HSM_JOB_STATE_SUSPENDED );
|
||
RETURN_STRINGIZED_CASE( HSM_JOB_STATE_SUSPENDING );
|
||
|
||
default:
|
||
|
||
return( OLESTR("Invalid Value") );
|
||
|
||
}
|
||
}
|
||
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::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("CHsmRecallQueue::FinalConstruct"),OLESTR(""));
|
||
try {
|
||
|
||
WsbAssertHr(CComObjectRoot::FinalConstruct());
|
||
|
||
//
|
||
// Initialize the member data
|
||
//
|
||
m_pServer = 0;
|
||
m_pHsmServerCreate = 0;
|
||
m_pTskMgr = 0;
|
||
|
||
m_pRmsServer = 0;
|
||
m_pRmsCartridge = 0;
|
||
m_pDataMover = 0;
|
||
|
||
m_pWorkToDo = 0;
|
||
|
||
UnsetMediaInfo();
|
||
|
||
m_HsmId = GUID_NULL;
|
||
m_RmsMediaSetId = GUID_NULL;
|
||
m_RmsMediaSetName = OLESTR("");
|
||
m_QueueType = HSM_WORK_TYPE_FSA_DEMAND_RECALL;
|
||
|
||
|
||
m_JobPriority = HSM_JOB_PRIORITY_NORMAL;
|
||
|
||
m_WorkerThread = 0;
|
||
m_CurrentPath = OLESTR("");
|
||
|
||
// Job abort on errors parameters
|
||
m_JobAbortMaxConsecutiveErrors = 5;
|
||
m_JobAbortMaxTotalErrors = 25;
|
||
m_JobConsecutiveErrors = 0;
|
||
m_JobTotalErrors = 0;
|
||
m_JobAbortSysDiskSpace = 2 * 1024 * 1024;
|
||
|
||
m_CurrentSeekOffset = 0;
|
||
|
||
WSB_OBJECT_ADD(CLSID_CHsmRecallQueue, this);
|
||
|
||
}WsbCatch(hr);
|
||
|
||
iCount++;
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::FinalConstruct"),OLESTR("hr = <%ls>, Count is <%d>"),
|
||
WsbHrAsString(hr), iCount);
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::FinalRelease(
|
||
void
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This method does some initialization of the object that is necessary
|
||
before destruction.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
S_OK
|
||
Anything returned by CWsbCollection::FinalDestruct().
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
HSM_SYSTEM_STATE SysState;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::FinalRelease"),OLESTR(""));
|
||
|
||
SysState.State = HSM_STATE_SHUTDOWN;
|
||
ChangeSysState(&SysState);
|
||
|
||
WSB_OBJECT_SUB(CLSID_CHsmRecallQueue, this);
|
||
CComObjectRoot::FinalRelease();
|
||
|
||
// Free String members
|
||
// Note: Member objects held in smart-pointers are freed when the
|
||
// smart-pointer destructor is being called (as part of this object destruction)
|
||
m_MediaName.Free();
|
||
m_MediaBarCode.Free();
|
||
m_RmsMediaSetName.Free();
|
||
m_CurrentPath.Free();
|
||
|
||
iCount--;
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::FinalRelease"),OLESTR("hr = <%ls>, Count is <%d>"),
|
||
WsbHrAsString(hr), iCount);
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::Init(
|
||
IUnknown *pServer,
|
||
IHsmFsaTskMgr *pTskMgr
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
This method does some initialization of the object that is necessary
|
||
after construction.
|
||
|
||
Arguments:
|
||
|
||
|
||
Return Value:
|
||
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
LONG rmsCartridgeType;
|
||
CComPtr<IRmsCartridge> pMedia;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::Init"),OLESTR(""));
|
||
try {
|
||
//
|
||
// Establish contact with the server and get the
|
||
// databases
|
||
//
|
||
WsbAffirmHr(pServer->QueryInterface(IID_IHsmServer, (void **)&m_pServer));
|
||
//We want a weak link to the server so decrement the reference count
|
||
m_pServer->Release();
|
||
|
||
m_pTskMgr = pTskMgr;
|
||
m_pTskMgr->AddRef();
|
||
m_QueueType = HSM_WORK_TYPE_FSA_DEMAND_RECALL;
|
||
|
||
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();
|
||
WsbAffirmHr(m_pServer->GetID(&m_HsmId));
|
||
//
|
||
// Make sure our connection to RMS is current
|
||
//
|
||
WsbAffirmHr(CheckRms());
|
||
|
||
//
|
||
// Get the media type. We assume mediaId is set before this
|
||
// is called. Imperative!
|
||
//
|
||
WsbAffirmHr(m_pRmsServer->FindCartridgeById(m_MediaId, &pMedia));
|
||
WsbAffirmHr(pMedia->GetType( &rmsCartridgeType ));
|
||
WsbAffirmHr(ConvertRmsCartridgeType(rmsCartridgeType, &m_MediaType));
|
||
|
||
//
|
||
// Make a collection for the work items
|
||
//
|
||
WsbAffirmHr(m_pHsmServerCreate->CreateInstance(CLSID_CWsbOrderedCollection,
|
||
IID_IWsbIndexedCollection,
|
||
(void **)&m_pWorkToDo ));
|
||
|
||
|
||
// Check the registry to see if there are changes to default settings
|
||
CheckRegistry();
|
||
}WsbCatch( hr );
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::Init"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
return( hr );
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::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
|
||
CHsmRecallQueue::ProcessSessionEvent( IHsmSession *pSession,
|
||
HSM_JOB_PHASE phase,
|
||
HSM_JOB_EVENT event
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::ProcessSessionEvent"),OLESTR(""));
|
||
try {
|
||
|
||
WsbAssert(0 != pSession, E_POINTER);
|
||
|
||
// If the phase applies to us (MOVER or ALL), then do any work required by the
|
||
// event.
|
||
if ((HSM_JOB_PHASE_ALL == phase) || (HSM_JOB_PHASE_MOVE_ACTION == phase)) {
|
||
|
||
switch (event) {
|
||
|
||
case HSM_JOB_EVENT_SUSPEND:
|
||
case HSM_JOB_EVENT_CANCEL:
|
||
case HSM_JOB_EVENT_FAIL:
|
||
WsbAffirmHr(Cancel(phase, pSession));
|
||
break;
|
||
|
||
case HSM_JOB_EVENT_RAISE_PRIORITY:
|
||
WsbAffirmHr(RaisePriority(phase, pSession));
|
||
break;
|
||
|
||
case HSM_JOB_EVENT_LOWER_PRIORITY:
|
||
WsbAffirmHr(LowerPriority(phase, pSession));
|
||
break;
|
||
|
||
default:
|
||
case HSM_JOB_EVENT_START:
|
||
WsbAssert(FALSE, E_UNEXPECTED);
|
||
break;
|
||
}
|
||
}
|
||
}WsbCatch(hr);
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::ProcessSessionEvent"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
return( S_OK );
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::ProcessSessionState(
|
||
IHsmSession* /*pSession*/,
|
||
IHsmPhase* pPhase,
|
||
OLECHAR* /*currentPath*/
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
|
||
|
||
--*/ {
|
||
HRESULT hr = S_OK;
|
||
HSM_JOB_PHASE phase;
|
||
HSM_JOB_STATE state;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::ProcessSessionState"),OLESTR(""));
|
||
try {
|
||
|
||
WsbAffirmHr(pPhase->GetState(&state));
|
||
WsbAffirmHr(pPhase->GetPhase(&phase));
|
||
WsbTrace( OLESTR("CHsmRecallQueue::ProcessSessionState - State = <%d>, phase = <%d>\n"), state, phase );
|
||
|
||
if (HSM_JOB_PHASE_SCAN == phase) {
|
||
|
||
// If the session has finished, then we have some cleanup to do so that it can go
|
||
// away.
|
||
if ((state == HSM_JOB_STATE_DONE) || (state == HSM_JOB_STATE_FAILED) || (state == HSM_JOB_STATE_SUSPENDED)) {
|
||
WsbTrace( OLESTR("Job is done, failed, or suspended\n") );
|
||
//
|
||
// Do nothing: when one recall item is done, we don't need to wait
|
||
// for the FSA in order to perform cleanup code
|
||
//
|
||
/*** WsbAffirmHr(MarkWorkItemAsDone(pSession, phase)); ***/
|
||
}
|
||
}
|
||
|
||
}WsbCatch( hr );
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::ProcessSessionState"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
return( S_OK );
|
||
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::Add(
|
||
IFsaPostIt *pFsaWorkItem,
|
||
GUID *pBagId,
|
||
LONGLONG dataSetStart
|
||
)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IHsmFsaTskMgr::Add
|
||
|
||
--*/ {
|
||
HRESULT hr = S_OK;
|
||
CComPtr<IHsmSession> pSession;
|
||
CComPtr<IWsbEnum> pEnum;
|
||
CComPtr<IHsmRecallItem> pWorkItem, pWorkItem2;
|
||
LONGLONG seekOffset, currentSeekOffset, prevSeekOffset;
|
||
LARGE_INTEGER remoteFileStart, remoteDataStart;
|
||
LONGLONG readOffset;
|
||
FSA_PLACEHOLDER placeholder;
|
||
HSM_WORK_ITEM_TYPE workType;
|
||
BOOL workItemAllocated=FALSE, insert;
|
||
CComPtr<IFsaFilterRecall> pRecall;
|
||
DWORD index = 0;
|
||
BOOL qLocked = FALSE;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::Add"),OLESTR(""));
|
||
try {
|
||
//
|
||
// Make sure there is a work allocater for this session
|
||
//
|
||
WsbAffirmHr(pFsaWorkItem->GetSession(&pSession));
|
||
//
|
||
// Create a work item, load it up and add it to this
|
||
// Queue's collection
|
||
//
|
||
CComPtr<IHsmRecallItem> pWorkItem;
|
||
WsbAffirmHr(m_pHsmServerCreate->CreateInstance(CLSID_CHsmRecallItem, IID_IHsmRecallItem,
|
||
(void **)&pWorkItem));
|
||
workItemAllocated = TRUE;
|
||
WsbAffirmHr(pWorkItem->SetWorkType(HSM_WORK_ITEM_FSA_WORK));
|
||
WsbAffirmHr(pWorkItem->SetFsaPostIt(pFsaWorkItem));
|
||
WsbAffirmHr(CheckSession(pSession, pWorkItem));
|
||
|
||
WsbAffirmHr(pWorkItem->SetBagId(pBagId));
|
||
WsbAffirmHr(pWorkItem->SetDataSetStart(dataSetStart));
|
||
|
||
if (m_MediaType == HSM_JOB_MEDIA_TYPE_TAPE) {
|
||
//
|
||
// For sequential media we order the requests to achieve
|
||
// optimal perf.
|
||
//
|
||
WsbAffirmHr(pFsaWorkItem->GetPlaceholder(&placeholder));
|
||
remoteFileStart.QuadPart = placeholder.fileStart;
|
||
remoteDataStart.QuadPart = placeholder.dataStart;
|
||
WsbAffirmHr(pFsaWorkItem->GetFilterRecall(&pRecall));
|
||
WsbAffirmHr(pRecall->GetOffset( &readOffset ));
|
||
|
||
//
|
||
// Calculate the offset in the media that needs to be seeked to
|
||
// for the recall. This will be only used for ordering the queue
|
||
// performance reasons.
|
||
//
|
||
seekOffset = dataSetStart + remoteFileStart.QuadPart + remoteDataStart.QuadPart + readOffset;
|
||
|
||
|
||
WsbAffirmHr(pWorkItem->SetSeekOffset(seekOffset));
|
||
index = 0;
|
||
//
|
||
// Find a position in the queue to insert it
|
||
// First, we lock the queue while we search for the position
|
||
// & insert the item into the queue. We make the assumption
|
||
// the lock protecting the queue is recursively acquirable.
|
||
// If this is not true, the code that adds to the queue will
|
||
// deadlock because it tries to lock the queue too!
|
||
//
|
||
m_pWorkToDo->Lock();
|
||
qLocked = TRUE;
|
||
|
||
WsbAffirmHr(m_pWorkToDo->Enum(&pEnum));
|
||
//
|
||
// If the seek offset of the item we wish to insert is
|
||
// > the current seek offset of the item that is in progress,
|
||
// we just insert it in the first monotonic ascending sequence.
|
||
// If not, we insert in the *second* monotonic ascending sequence,
|
||
// to prevent the head from seeking back prematurely
|
||
//
|
||
hr = pEnum->First(IID_IHsmRecallItem, (void **)&pWorkItem2);
|
||
if (seekOffset > m_CurrentSeekOffset) {
|
||
//
|
||
// Insert in the first ascending sequence
|
||
//
|
||
insert = TRUE;
|
||
} else {
|
||
//
|
||
// Skip the first ascending sequence
|
||
//
|
||
insert = FALSE;
|
||
}
|
||
|
||
prevSeekOffset = 0;
|
||
while (hr != WSB_E_NOTFOUND) {
|
||
WsbAffirmHr(pWorkItem2->GetWorkType(&workType));
|
||
|
||
if (workType != HSM_WORK_ITEM_FSA_WORK) {
|
||
//
|
||
// Not interested in this. Release it before getting the next
|
||
//
|
||
pWorkItem2 = 0;
|
||
hr = pEnum->Next(IID_IHsmRecallItem, (void **)&pWorkItem2);
|
||
index++;
|
||
continue;
|
||
}
|
||
|
||
WsbAffirmHr(pWorkItem2->GetSeekOffset(¤tSeekOffset));
|
||
|
||
if (insert && (currentSeekOffset > seekOffset)) {
|
||
//
|
||
// place to insert the item..
|
||
//
|
||
break;
|
||
}
|
||
|
||
if (!insert && (currentSeekOffset < prevSeekOffset)) {
|
||
//
|
||
// Start of second monotone sequence. We wish to insert
|
||
// the item in this sequence
|
||
//
|
||
insert = TRUE;
|
||
//
|
||
// Check if pWorkItem is eligible to be inserted at this
|
||
// index position
|
||
//
|
||
if (currentSeekOffset > seekOffset) {
|
||
//
|
||
// place to insert the item..
|
||
//
|
||
break;
|
||
}
|
||
} else {
|
||
prevSeekOffset = currentSeekOffset;
|
||
}
|
||
//
|
||
// Move on to the next. Release the current item first
|
||
//
|
||
pWorkItem2 = 0;
|
||
hr = pEnum->Next(IID_IHsmRecallItem, (void **)&pWorkItem2);
|
||
index++;
|
||
|
||
}
|
||
if (hr == WSB_E_NOTFOUND) {
|
||
WsbAffirmHr(m_pWorkToDo->Append(pWorkItem));
|
||
} else {
|
||
WsbAffirmHr(m_pWorkToDo->AddAt(pWorkItem, index));
|
||
}
|
||
//
|
||
// Safe to unlock the queue
|
||
//
|
||
m_pWorkToDo->Unlock();
|
||
qLocked = FALSE;
|
||
|
||
} else {
|
||
//
|
||
// For non-sequential media, we just add it to the queue ...
|
||
// No ordering is done, we let the file system do the optimizations
|
||
//
|
||
WsbAffirmHr(m_pWorkToDo->Append(pWorkItem));
|
||
}
|
||
hr = S_OK;
|
||
}WsbCatchAndDo(hr,
|
||
//
|
||
// Add code to release queue lock if acquired
|
||
//
|
||
if (qLocked) {
|
||
m_pWorkToDo->Unlock();
|
||
}
|
||
);
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::Add"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::Start( void )
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IHsmRecallQueue::Start
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
DWORD tid;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::Start"),OLESTR(""));
|
||
try {
|
||
//
|
||
// If the worker thread is already started, just return
|
||
//
|
||
WsbAffirm(m_WorkerThread == 0, S_OK);
|
||
// Launch a thread to do work that is queued
|
||
WsbAffirm((m_WorkerThread = CreateThread(0, 0, HsmRecallQueueThread, (void*) this, 0, &tid)) != 0, HRESULT_FROM_WIN32(GetLastError()));
|
||
|
||
if (m_WorkerThread == NULL) {
|
||
WsbAssertHr(E_FAIL); // TBD What error to return here??
|
||
}
|
||
|
||
}WsbCatch (hr);
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::Start"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::Stop( void )
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IHsmRecallQueue::Stop
|
||
|
||
--*/ {
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::Stop"),OLESTR(""));
|
||
|
||
// Stop the thread
|
||
if (m_WorkerThread) {
|
||
TerminateThread(m_WorkerThread, 0);
|
||
}
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::Stop"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
return(hr);
|
||
}
|
||
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::RecallIt(
|
||
IHsmRecallItem * pWorkItem
|
||
)
|
||
{
|
||
HRESULT hr = S_OK;
|
||
CComPtr<IFsaScanItem> pScanItem;
|
||
CComPtr<IFsaPostIt> pFsaWorkItem;
|
||
LONGLONG readOffset;
|
||
FSA_REQUEST_ACTION requestAction;
|
||
ULARGE_INTEGER remoteDataSetStart;
|
||
GUID bagId;
|
||
|
||
CComPtr<IWsbIndexedCollection> pMountingCollection;
|
||
CComPtr<IMountingMedia> pMountingMedia;
|
||
CComPtr<IMountingMedia> pMediaToFind;
|
||
BOOL bMediaMounting = FALSE;
|
||
BOOL bMediaMountingAdded = FALSE;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::RecallIt"),OLESTR(""));
|
||
try {
|
||
|
||
WsbAffirmHr(pWorkItem->GetFsaPostIt(&pFsaWorkItem));
|
||
|
||
WsbAffirmHr(pFsaWorkItem->GetRequestAction(&requestAction));
|
||
GetScanItem(pFsaWorkItem, &pScanItem);
|
||
|
||
WsbAffirmHr(pWorkItem->GetBagId(&bagId));
|
||
WsbAffirmHr(pWorkItem->GetDataSetStart((LONGLONG *) &remoteDataSetStart.QuadPart));
|
||
|
||
//
|
||
// Check if we are mounting a new media: recall-queue is created on a per-media basis, therefore,
|
||
// media cannot change. The only test is whether the media for this queue is already mounted
|
||
//
|
||
if (m_MountedMedia == GUID_NULL) {
|
||
|
||
// Check if the media is already in the process of mounting
|
||
WsbAffirmHr(m_pServer->LockMountingMedias());
|
||
|
||
try {
|
||
// Check if the media to mount is already mounting
|
||
WsbAffirmHr(m_pServer->GetMountingMedias(&pMountingCollection));
|
||
WsbAffirmHr(CoCreateInstance(CLSID_CMountingMedia, 0, CLSCTX_SERVER, IID_IMountingMedia, (void**)&pMediaToFind));
|
||
WsbAffirmHr(pMediaToFind->SetMediaId(m_MediaId));
|
||
hr = pMountingCollection->Find(pMediaToFind, IID_IMountingMedia, (void **)&pMountingMedia);
|
||
|
||
if (hr == S_OK) {
|
||
// Media is already mounting...
|
||
bMediaMounting = TRUE;
|
||
|
||
} else if (hr == WSB_E_NOTFOUND) {
|
||
// New media to mount - add to the mounting list
|
||
hr = S_OK;
|
||
WsbAffirmHr(pMediaToFind->Init(m_MediaId, TRUE));
|
||
WsbAffirmHr(pMountingCollection->Add(pMediaToFind));
|
||
bMediaMountingAdded = TRUE;
|
||
|
||
} else {
|
||
WsbAffirmHr(hr);
|
||
}
|
||
} WsbCatchAndDo(hr,
|
||
// Unlock mounting media
|
||
m_pServer->UnlockMountingMedias();
|
||
|
||
WsbTraceAlways(OLESTR("CHsmRecallQueue::RecallIt: error while trying to find/add mounting media. hr=<%ls>\n"),
|
||
WsbHrAsString(hr));
|
||
|
||
// Bale out
|
||
WsbThrow(hr);
|
||
);
|
||
|
||
// Release the lock
|
||
WsbAffirmHr(m_pServer->UnlockMountingMedias());
|
||
}
|
||
|
||
//
|
||
// If the media is already mounting - wait for the mount event
|
||
//
|
||
if (bMediaMounting) {
|
||
WsbAffirmHr(pMountingMedia->WaitForMount(INFINITE));
|
||
pMountingMedia = 0;
|
||
}
|
||
|
||
//
|
||
// Get the media mounted (hr is checked only after removing from the mounting-media list)
|
||
//
|
||
hr = MountMedia(pWorkItem, m_MediaId);
|
||
|
||
//
|
||
// If added to the mounting list - remove
|
||
//
|
||
if (bMediaMountingAdded) {
|
||
HRESULT hrRemove = S_OK;
|
||
|
||
// No matter how the Mount finished - free waiting clients and remove from the list
|
||
hrRemove = m_pServer->LockMountingMedias();
|
||
WsbAffirmHr(hrRemove);
|
||
|
||
try {
|
||
WsbAffirmHr(pMediaToFind->MountDone());
|
||
WsbAffirmHr(pMountingCollection->RemoveAndRelease(pMediaToFind));
|
||
pMediaToFind = 0;
|
||
|
||
} WsbCatch(hrRemove);
|
||
|
||
m_pServer->UnlockMountingMedias();
|
||
|
||
// We don't expect any errors while removing the mounting media -
|
||
// The thread that added to the collection is always the one that removes
|
||
if (! SUCCEEDED(hrRemove)) {
|
||
WsbTraceAlways(OLESTR("CHsmRecallQueue::RecallIt: error while trying to remove a mounting media. hr=<%ls>\n"),
|
||
WsbHrAsString(hrRemove));
|
||
|
||
WsbThrow(hrRemove);
|
||
}
|
||
}
|
||
|
||
//
|
||
// Check the Mount result
|
||
//
|
||
WsbAffirmHr(hr);
|
||
|
||
//
|
||
// Copy the data
|
||
//
|
||
// Build the source path
|
||
CWsbStringPtr tmpString;
|
||
WsbAffirmHr(GetSource(pFsaWorkItem, &tmpString));
|
||
CWsbBstrPtr localName = tmpString;
|
||
// Ask the Data mover to store the data
|
||
LONGLONG requestSize;
|
||
LONGLONG requestStart;
|
||
ULARGE_INTEGER localDataStart;
|
||
ULARGE_INTEGER localDataSize;
|
||
ULARGE_INTEGER remoteFileStart;
|
||
ULARGE_INTEGER remoteFileSize;
|
||
ULARGE_INTEGER remoteDataStart;
|
||
ULARGE_INTEGER remoteDataSize;
|
||
ULARGE_INTEGER remoteVerificationData;
|
||
ULONG remoteVerificationType;
|
||
|
||
FSA_PLACEHOLDER placeholder;
|
||
WsbAffirmHr(pFsaWorkItem->GetPlaceholder(&placeholder));
|
||
WsbAffirmHr(pFsaWorkItem->GetRequestSize(&requestSize));
|
||
WsbAffirmHr(pFsaWorkItem->GetRequestOffset(&requestStart));
|
||
|
||
//
|
||
// Build strings
|
||
//
|
||
CWsbBstrPtr sessionName = HSM_BAG_NAME;
|
||
CWsbBstrPtr sessionDescription = HSM_ENGINE_ID;
|
||
sessionName.Append(WsbGuidAsString(bagId));
|
||
sessionDescription.Append(WsbGuidAsString(m_HsmId));
|
||
|
||
localDataStart.QuadPart = requestStart;
|
||
localDataSize.QuadPart = requestSize;
|
||
remoteFileStart.QuadPart = placeholder.fileStart;
|
||
remoteFileSize.QuadPart = placeholder.fileSize;
|
||
remoteDataStart.QuadPart = placeholder.dataStart;
|
||
remoteDataSize.QuadPart = placeholder.dataSize;
|
||
remoteVerificationData.QuadPart = placeholder.verificationData;
|
||
remoteVerificationType = placeholder.verificationType;
|
||
|
||
|
||
ReportMediaProgress(HSM_JOB_MEDIA_STATE_TRANSFERRING, hr);
|
||
|
||
CComPtr<IStream> pLocalStream;
|
||
CComPtr<IStream> pRemoteStream;
|
||
ULARGE_INTEGER offset, read, written;
|
||
DWORD verifyType;
|
||
|
||
//
|
||
// We are doing a demand recall, so get the
|
||
// recall object's data mover
|
||
//
|
||
CComPtr<IFsaFilterRecall> pRecall;
|
||
WsbAffirmHr(pFsaWorkItem->GetFilterRecall(&pRecall));
|
||
WsbAffirmHr(pRecall->CreateLocalStream( &pLocalStream));
|
||
WsbAffirmHr(pRecall->GetSize( (LONGLONG *) &remoteDataSize.QuadPart ));
|
||
WsbAffirmHr(pRecall->GetOffset( &readOffset ));
|
||
if (readOffset == 0) {
|
||
verifyType = MVR_VERIFICATION_TYPE_HEADER_CRC;
|
||
} else {
|
||
verifyType = MVR_VERIFICATION_TYPE_NONE;
|
||
}
|
||
|
||
//
|
||
// Set the current seek offset used for ordering items in the queue
|
||
//
|
||
m_CurrentSeekOffset = remoteDataSetStart.QuadPart + remoteFileStart.QuadPart+remoteDataStart.QuadPart+requestStart;
|
||
|
||
//
|
||
// Create remote data mover stream
|
||
// TEMPORARY: Consider removing the NO_CACHING flag for a NO_RECALL recall
|
||
//
|
||
|
||
WsbAssert(0 != remoteDataSetStart.QuadPart, HSM_E_BAD_SEGMENT_INFORMATION);
|
||
WsbAffirmHr( m_pDataMover->CreateRemoteStream(
|
||
CWsbBstrPtr(L""),
|
||
MVR_MODE_READ | MVR_FLAG_HSM_SEMANTICS | MVR_FLAG_NO_CACHING,
|
||
sessionName,
|
||
sessionDescription,
|
||
remoteDataSetStart,
|
||
remoteFileStart,
|
||
remoteFileSize,
|
||
remoteDataStart,
|
||
remoteDataSize,
|
||
verifyType,
|
||
remoteVerificationData,
|
||
&pRemoteStream ) );
|
||
|
||
//
|
||
// The offset given here is the offset into the stream itself (readOffset).
|
||
// The actual position on remote media will be the bag start plus the file start
|
||
// plus the file-data start (all given in CreateRemoteStream) plus this offset.
|
||
//
|
||
WsbTrace(OLESTR("Setting offset to %I64d reading %I64u\n"), readOffset, remoteDataSize.QuadPart);
|
||
|
||
offset.QuadPart = readOffset;
|
||
WsbAffirmHr( m_pDataMover->SetInitialOffset( offset ) );
|
||
|
||
//
|
||
// Once the remote stream has been created we must make sure we detach it
|
||
//
|
||
|
||
try {
|
||
|
||
WsbAffirmHr( pRemoteStream->CopyTo( pLocalStream, remoteDataSize, &read, &written ) );
|
||
WsbAffirmHr( pLocalStream->Commit( STGC_DEFAULT ) );
|
||
|
||
//
|
||
// The CopyTo succeeded... make sure we got all the bytes
|
||
// we asked for.
|
||
//
|
||
// If we attempt to read from a incomplete Master that
|
||
// does not contain the migrated data we'll fail here with
|
||
// MVR_S_NO_DATA_DETECTED.
|
||
//
|
||
WsbAffirm( written.QuadPart == remoteDataSize.QuadPart, HSM_E_VALIDATE_DATA_NOT_ON_MEDIA );
|
||
|
||
WsbAffirmHr( m_pDataMover->CloseStream() );
|
||
}WsbCatchAndDo(hr,
|
||
WsbAffirmHr( m_pDataMover->CloseStream() );
|
||
);
|
||
|
||
ReportMediaProgress(HSM_JOB_MEDIA_STATE_TRANSFERRED, hr);
|
||
WsbTrace(OLESTR("RecallData returned hr = <%ls>\n"),WsbHrAsString(hr));
|
||
|
||
}WsbCatch( hr );
|
||
|
||
// Tell the session whether or not the work was done.
|
||
// We don't really care about the return code, there is nothing
|
||
// we can do if it fails.
|
||
WsbTrace(OLESTR("Tried HSM work, calling Session to Process Item\n"));
|
||
if (pScanItem) {
|
||
CComPtr<IHsmSession> pSession;
|
||
HSM_JOB_PHASE jobPhase;
|
||
|
||
WsbAffirmHr(pFsaWorkItem->GetSession(&pSession));
|
||
|
||
WsbAffirmHr(pWorkItem->GetJobPhase(&jobPhase));
|
||
|
||
pSession->ProcessItem(jobPhase, HSM_JOB_ACTION_RECALL , pScanItem, hr);
|
||
}
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::RecallIt"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
return( hr );
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::RaisePriority(
|
||
IN HSM_JOB_PHASE jobPhase,
|
||
IN IHsmSession *pSession
|
||
)
|
||
|
||
/*++
|
||
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::RaisePriority"),OLESTR(""));
|
||
try {
|
||
|
||
WsbAssert(0 != m_WorkerThread, E_UNEXPECTED);
|
||
WsbAssert(pSession != 0, E_UNEXPECTED);
|
||
|
||
switch (m_JobPriority) {
|
||
|
||
case HSM_JOB_PRIORITY_IDLE:
|
||
WsbAffirmStatus(SetThreadPriority(m_WorkerThread, THREAD_PRIORITY_LOWEST));
|
||
m_JobPriority = HSM_JOB_PRIORITY_LOWEST;
|
||
break;
|
||
|
||
case HSM_JOB_PRIORITY_LOWEST:
|
||
WsbAffirmStatus(SetThreadPriority(m_WorkerThread, THREAD_PRIORITY_BELOW_NORMAL));
|
||
m_JobPriority = HSM_JOB_PRIORITY_LOW;
|
||
break;
|
||
|
||
case HSM_JOB_PRIORITY_LOW:
|
||
WsbAffirmStatus(SetThreadPriority(m_WorkerThread, THREAD_PRIORITY_NORMAL));
|
||
m_JobPriority = HSM_JOB_PRIORITY_NORMAL;
|
||
break;
|
||
|
||
case HSM_JOB_PRIORITY_NORMAL:
|
||
WsbAffirmStatus(SetThreadPriority(m_WorkerThread, THREAD_PRIORITY_ABOVE_NORMAL));
|
||
m_JobPriority = HSM_JOB_PRIORITY_HIGH;
|
||
break;
|
||
|
||
case HSM_JOB_PRIORITY_HIGH:
|
||
WsbAffirmStatus(SetThreadPriority(m_WorkerThread, THREAD_PRIORITY_HIGHEST));
|
||
m_JobPriority = HSM_JOB_PRIORITY_HIGHEST;
|
||
break;
|
||
|
||
case HSM_JOB_PRIORITY_HIGHEST:
|
||
WsbAffirmStatus(SetThreadPriority(m_WorkerThread, THREAD_PRIORITY_TIME_CRITICAL));
|
||
m_JobPriority = HSM_JOB_PRIORITY_CRITICAL;
|
||
break;
|
||
|
||
default:
|
||
case HSM_JOB_PRIORITY_CRITICAL:
|
||
WsbAffirm(FALSE, E_UNEXPECTED);
|
||
break;
|
||
}
|
||
|
||
WsbAffirmHr(pSession->ProcessPriority(jobPhase, m_JobPriority));
|
||
|
||
}WsbCatch(hr);
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::RaisePriority"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::LowerPriority(
|
||
IN HSM_JOB_PHASE jobPhase,
|
||
IN IHsmSession *pSession
|
||
)
|
||
|
||
/*++
|
||
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::LowerPriority"),OLESTR(""));
|
||
try {
|
||
|
||
WsbAssert(0 != m_WorkerThread, E_UNEXPECTED);
|
||
WsbAssert(pSession != 0, E_UNEXPECTED);
|
||
|
||
switch (m_JobPriority) {
|
||
case HSM_JOB_PRIORITY_IDLE:
|
||
WsbAffirm(FALSE, E_UNEXPECTED);
|
||
break;
|
||
|
||
case HSM_JOB_PRIORITY_LOWEST:
|
||
WsbAffirmStatus(SetThreadPriority(m_WorkerThread, THREAD_PRIORITY_IDLE));
|
||
m_JobPriority = HSM_JOB_PRIORITY_IDLE;
|
||
break;
|
||
|
||
case HSM_JOB_PRIORITY_LOW:
|
||
WsbAffirmStatus(SetThreadPriority(m_WorkerThread, THREAD_PRIORITY_LOWEST));
|
||
m_JobPriority = HSM_JOB_PRIORITY_LOWEST;
|
||
break;
|
||
|
||
case HSM_JOB_PRIORITY_NORMAL:
|
||
WsbAffirmStatus(SetThreadPriority(m_WorkerThread, THREAD_PRIORITY_BELOW_NORMAL));
|
||
m_JobPriority = HSM_JOB_PRIORITY_LOW;
|
||
break;
|
||
|
||
case HSM_JOB_PRIORITY_HIGH:
|
||
WsbAffirmStatus(SetThreadPriority(m_WorkerThread, THREAD_PRIORITY_NORMAL));
|
||
m_JobPriority = HSM_JOB_PRIORITY_NORMAL;
|
||
break;
|
||
|
||
case HSM_JOB_PRIORITY_HIGHEST:
|
||
WsbAffirmStatus(SetThreadPriority(m_WorkerThread, THREAD_PRIORITY_ABOVE_NORMAL));
|
||
m_JobPriority = HSM_JOB_PRIORITY_HIGH;
|
||
break;
|
||
|
||
default:
|
||
case HSM_JOB_PRIORITY_CRITICAL:
|
||
WsbAffirmStatus(SetThreadPriority(m_WorkerThread, THREAD_PRIORITY_HIGHEST));
|
||
m_JobPriority = HSM_JOB_PRIORITY_HIGHEST;
|
||
break;
|
||
}
|
||
|
||
WsbAffirmHr(pSession->ProcessPriority(jobPhase, m_JobPriority));
|
||
|
||
}WsbCatch(hr);
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::LowerPriority"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
return(hr);
|
||
}
|
||
|
||
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::CheckRms(
|
||
void
|
||
)
|
||
|
||
/*++
|
||
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::CheckRms"),OLESTR(""));
|
||
try {
|
||
//
|
||
// Make sure we can still talk to the RMS
|
||
//
|
||
if (m_pRmsServer != 0) {
|
||
CWsbBstrPtr name;
|
||
hr = m_pRmsServer->GetServerName( &name );
|
||
if (hr != S_OK) {
|
||
m_pRmsServer = 0;
|
||
hr = S_OK;
|
||
}
|
||
}
|
||
//
|
||
// Get RMS that runs on this machine
|
||
//
|
||
if (m_pRmsServer == 0) {
|
||
WsbAffirmHr(m_pServer->GetHsmMediaMgr(&m_pRmsServer));
|
||
|
||
// wait for RMS to come ready
|
||
// (this may not be needed anymore - if Rms initialization is
|
||
// synced with Engine initialization)
|
||
CComObject<CRmsSink> *pSink = new CComObject<CRmsSink>;
|
||
CComPtr<IUnknown> pSinkUnk = pSink; // holds refcount for use here
|
||
WsbAffirmHr( pSink->Construct( m_pRmsServer ) );
|
||
WsbAffirmHr( pSink->WaitForReady( ) );
|
||
WsbAffirmHr( pSink->DoUnadvise( ) );
|
||
}
|
||
}WsbCatch( hr );
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::CheckRms"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
return(hr);
|
||
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::CheckSession(
|
||
IHsmSession *pSession,
|
||
IHsmRecallItem *pWorkItem
|
||
)
|
||
|
||
/*++
|
||
|
||
|
||
--*/ {
|
||
HRESULT hr = S_OK;
|
||
BOOL bLog = TRUE;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::CheckSession"),OLESTR(""));
|
||
try {
|
||
|
||
//
|
||
// Check to see if we have dealt with this or any other session before.
|
||
WsbTrace(OLESTR("New session.\n"));
|
||
|
||
//
|
||
// We have no on going session so we need to establish communication
|
||
// with this session.
|
||
//
|
||
CComPtr<IHsmSessionSinkEveryState> pSinkState;
|
||
CComPtr<IHsmSessionSinkEveryEvent> pSinkEvent;
|
||
CComPtr<IConnectionPointContainer> pCPC;
|
||
CComPtr<IConnectionPoint> pCP;
|
||
CComPtr<IFsaResource> pFsaResource;
|
||
HSM_JOB_PHASE jobPhase;
|
||
DWORD stateCookie, eventCookie;
|
||
ULONG refCount;
|
||
|
||
// Tell the session we are starting up.
|
||
pWorkItem->SetJobState(HSM_JOB_STATE_STARTING);
|
||
pWorkItem->GetJobPhase(&jobPhase);
|
||
WsbTrace(OLESTR("Before Process State.\n"));
|
||
refCount = (((IUnknown *) (IHsmFsaTskMgr *) this)->AddRef()) - 1;
|
||
((IUnknown *) (IHsmFsaTskMgr *)this)->Release();
|
||
WsbTrace(OLESTR("REFCOUNT for CHsmRecallQueue before 1st process state: %ls \n"), WsbLongAsString((LONG) refCount));
|
||
WsbAffirmHr(pSession->ProcessState(jobPhase, HSM_JOB_STATE_STARTING, m_CurrentPath, bLog));
|
||
refCount = (((IUnknown *) (IHsmFsaTskMgr *) this)->AddRef()) - 1;
|
||
((IUnknown *) (IHsmFsaTskMgr *)this)->Release();
|
||
WsbTrace(OLESTR("REFCOUNT for CHsmRecallQueue after 1st process state: %ls \n"), WsbLongAsString((LONG) refCount));
|
||
WsbTrace(OLESTR("After Process State.\n"));
|
||
|
||
// Get the interface to the callback that the sessions should use.
|
||
WsbTrace(OLESTR("Before QI's for sinks.\n"));
|
||
WsbAffirmHr(((IUnknown*) (IHsmFsaTskMgr*) this)->QueryInterface(IID_IHsmSessionSinkEveryState, (void**) &pSinkState));
|
||
WsbAffirmHr(((IUnknown*) (IHsmFsaTskMgr*) this)->QueryInterface(IID_IHsmSessionSinkEveryEvent, (void**) &pSinkEvent));
|
||
WsbTrace(OLESTR("After QI's for sinks.\n"));
|
||
// Ask the session to advise of every state changes.
|
||
WsbTrace(OLESTR("Before QI for connection point containers.\n"));
|
||
|
||
WsbAffirmHr(pSession->QueryInterface(IID_IConnectionPointContainer, (void**) &pCPC));
|
||
WsbAffirmHr(pCPC->FindConnectionPoint(IID_IHsmSessionSinkEveryState, &pCP));
|
||
WsbAffirmHr(pCP->Advise(pSinkState, &stateCookie));
|
||
|
||
pWorkItem->SetStateCookie(stateCookie);
|
||
pCP = 0;
|
||
|
||
WsbAffirmHr(pCPC->FindConnectionPoint(IID_IHsmSessionSinkEveryEvent, &pCP));
|
||
WsbAffirmHr(pCP->Advise(pSinkEvent, &eventCookie));
|
||
pWorkItem->SetEventCookie(eventCookie);
|
||
|
||
pCP = 0;
|
||
WsbTrace(OLESTR("After Advises.\n"));
|
||
//
|
||
// Get the resource for this work from the session
|
||
//
|
||
WsbAffirmHr(pSession->GetResource(&pFsaResource));
|
||
pWorkItem->SetJobState(HSM_JOB_STATE_ACTIVE);
|
||
|
||
WsbTrace(OLESTR("Before Process State.\n"));
|
||
|
||
refCount = (((IUnknown *) (IHsmFsaTskMgr *) this)->AddRef()) - 1;
|
||
((IUnknown *) (IHsmFsaTskMgr *)this)->Release();
|
||
WsbTrace(OLESTR("REFCOUNT for CHsmRecallQueue before 2nd process state: %ls \n"), WsbLongAsString((LONG) refCount));
|
||
|
||
WsbAffirmHr(pSession->ProcessState(jobPhase, HSM_JOB_STATE_ACTIVE, m_CurrentPath, bLog));
|
||
|
||
refCount = (((IUnknown *) (IHsmFsaTskMgr *) this)->AddRef()) - 1;
|
||
((IUnknown *) (IHsmFsaTskMgr *)this)->Release();
|
||
WsbTrace(OLESTR("REFCOUNT for CHsmRecallQueue after 2nd process state: %ls \n"), WsbLongAsString((LONG) refCount));
|
||
|
||
WsbTrace(OLESTR("After Process State.\n"));
|
||
|
||
}WsbCatch( hr );
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::CheckSession"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
return(hr);
|
||
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::DoWork( void )
|
||
/*++
|
||
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
CWsbStringPtr path;
|
||
CComPtr<IHsmRecallItem> pWorkItem;
|
||
HSM_WORK_ITEM_TYPE workType;
|
||
BOOLEAN done = FALSE;
|
||
HRESULT skipWork = S_FALSE;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::DoWork"),OLESTR(""));
|
||
|
||
// Make sure this object isn't released (and our thread killed
|
||
// before finishing up in this routine
|
||
((IUnknown*)(IHsmRecallQueue*)this)->AddRef();
|
||
|
||
try {
|
||
while (!done) {
|
||
//
|
||
// Get the next work to do from the queue
|
||
//
|
||
hr = m_pWorkToDo->First(IID_IHsmRecallItem, (void **)&pWorkItem);
|
||
|
||
if (WSB_E_NOTFOUND == hr) {
|
||
//
|
||
// We might be done with this queue.
|
||
// Attempt to destroy it: if we cannot it means there are more items
|
||
// that were being added so we continue looping
|
||
//
|
||
hr = m_pTskMgr->WorkQueueDone(NULL, HSM_WORK_TYPE_FSA_DEMAND_RECALL, &m_MediaId);
|
||
if (hr == S_OK) {
|
||
//
|
||
// Queue is really done - break out of the while loop
|
||
//
|
||
done = TRUE;
|
||
break;
|
||
} else if (hr == S_FALSE) {
|
||
//
|
||
// More items in the queue
|
||
//
|
||
continue;
|
||
} else {
|
||
//
|
||
// Some sort of error happened, bale out
|
||
//
|
||
WsbTraceAlways(OLESTR("CHsmRecallQueue::DoWork: WorkQueueDone failed with <%ls> - terminating queue thread\n"),
|
||
WsbHrAsString(hr));
|
||
WsbAffirmHr(hr);
|
||
}
|
||
} else {
|
||
WsbAffirmHr(hr);
|
||
//
|
||
// Remove it from the queue
|
||
//
|
||
Remove(pWorkItem);
|
||
|
||
}
|
||
|
||
WsbAffirmHr(pWorkItem->GetWorkType(&workType));
|
||
|
||
switch (workType) {
|
||
|
||
case HSM_WORK_ITEM_FSA_DONE: {
|
||
//
|
||
// TBD:Code path should not be reached
|
||
//
|
||
WsbTraceAlways(OLESTR("Unexpected: CHsmRecallQueue::DoWork - FSA WORK DONE item\n"));
|
||
|
||
break;
|
||
}
|
||
|
||
case HSM_WORK_ITEM_FSA_WORK: {
|
||
if (S_FALSE == skipWork) {
|
||
//
|
||
// Get the FSA Work Item and do the work
|
||
//
|
||
hr = DoFsaWork(pWorkItem);
|
||
} else {
|
||
//
|
||
// Skip the work
|
||
//
|
||
try {
|
||
CComPtr<IFsaPostIt> pFsaWorkItem;
|
||
CComPtr<IFsaScanItem> pScanItem;
|
||
CComPtr<IFsaResource> pFsaResource;
|
||
CComPtr<IHsmSession> pSession;
|
||
HSM_JOB_PHASE jobPhase;
|
||
|
||
WsbAffirmHr(pWorkItem->GetFsaPostIt(&pFsaWorkItem));
|
||
WsbAffirmHr(pWorkItem->GetJobPhase(&jobPhase));
|
||
WsbAffirmHr(pFsaWorkItem->GetSession(&pSession));
|
||
WsbAffirmHr(pSession->GetResource(&pFsaResource));
|
||
WsbAffirmHr(GetScanItem(pFsaWorkItem, &pScanItem));
|
||
|
||
hr = pFsaWorkItem->SetResult(skipWork);
|
||
|
||
if (S_OK == hr) {
|
||
WsbTrace(OLESTR("HSM recall (filter, read or recall) complete, calling FSA\n"));
|
||
hr = pFsaResource->ProcessResult(pFsaWorkItem);
|
||
WsbTrace(OLESTR("FSA ProcessResult returned <%ls>\n"), WsbHrAsString(hr));
|
||
}
|
||
(void)pSession->ProcessHr(jobPhase, 0, 0, hr);
|
||
WsbAffirmHr(pSession->ProcessItem(jobPhase,
|
||
HSM_JOB_ACTION_RECALL,
|
||
pScanItem,
|
||
skipWork));
|
||
}WsbCatch( hr );
|
||
}
|
||
EndRecallSession(pWorkItem, FALSE);
|
||
|
||
break;
|
||
}
|
||
|
||
case HSM_WORK_ITEM_MOVER_CANCELLED: {
|
||
CComPtr<IHsmRecallItem> pWorkItemToCancel;
|
||
|
||
WsbTrace(OLESTR("CHsmRecallQueue::DoWork - Mover Cancelled\n"));
|
||
try {
|
||
//
|
||
// Get hold of the work item that needs to be cancelled.
|
||
// This is indicated by the session pointer in the cancel work item
|
||
//
|
||
hr = FindRecallItemToCancel(pWorkItem, &pWorkItemToCancel);
|
||
if (hr == S_OK) {
|
||
EndRecallSession(pWorkItemToCancel, TRUE);
|
||
//
|
||
// Remove the *cancelled* work item
|
||
//
|
||
Remove(pWorkItemToCancel);
|
||
}
|
||
|
||
//
|
||
// Remove the cancel work item
|
||
//
|
||
hr = S_OK;
|
||
}WsbCatch( hr );
|
||
//
|
||
// We are done completely with one more work item
|
||
//
|
||
break;
|
||
}
|
||
|
||
default: {
|
||
hr = E_UNEXPECTED;
|
||
break;
|
||
}
|
||
}
|
||
pWorkItem = 0;
|
||
}
|
||
}WsbCatch( hr );
|
||
|
||
//
|
||
// Dismount the media..
|
||
//
|
||
DismountMedia(FALSE);
|
||
|
||
// Pretend everything is OK
|
||
hr = S_OK;
|
||
|
||
// Release the thread (the thread should terminate on exit
|
||
// from the routine that called this routine)
|
||
CloseHandle(m_WorkerThread);
|
||
m_WorkerThread = 0;
|
||
|
||
// Allow this object to be released
|
||
((IUnknown*)(IHsmRecallQueue*)this)->Release();
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::DoWork"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
return(hr);
|
||
}
|
||
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::DoFsaWork(
|
||
IHsmRecallItem *pWorkItem
|
||
)
|
||
/*++
|
||
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
HRESULT hr2 = S_OK;
|
||
HRESULT workHr = S_OK;
|
||
HSM_JOB_PHASE jobPhase;
|
||
|
||
CWsbStringPtr path;
|
||
CComPtr<IFsaPostIt> pFsaWorkItem;
|
||
CComPtr<IHsmSession> pSession;
|
||
CComPtr<IFsaResource> pFsaResource;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::DoFsaWork"),OLESTR(""));
|
||
try {
|
||
//
|
||
// Do the work.
|
||
//
|
||
WsbAffirmHr(pWorkItem->GetFsaPostIt(&pFsaWorkItem));
|
||
WsbAffirmHr(pWorkItem->GetJobPhase(&jobPhase));
|
||
WsbAffirmHr(pFsaWorkItem->GetPath(&path, 0));
|
||
WsbAffirmHr(pFsaWorkItem->GetSession(&pSession));
|
||
WsbAffirmHr(pSession->GetResource(&pFsaResource));
|
||
|
||
WsbTrace(OLESTR("Handling file <%s>.\n"), WsbAbbreviatePath(path, 120));
|
||
workHr = RecallIt(pWorkItem);
|
||
//
|
||
// Tell the recaller right away about the success or failure
|
||
// of the recall, we do this here so the recall filter can
|
||
// release the open as soon as possible
|
||
//
|
||
hr = pFsaWorkItem->SetResult(workHr);
|
||
if (S_OK == hr) {
|
||
WsbTrace(OLESTR("HSM recall (filter, read or recall) complete, calling FSA\n"));
|
||
hr = pFsaResource->ProcessResult(pFsaWorkItem);
|
||
WsbTrace(OLESTR("FSA ProcessResult returned <%ls>\n"), WsbHrAsString(hr));
|
||
}
|
||
|
||
// Note: In case that the recall item is/was canceling at any time, we don't want
|
||
// to report on errors. If the cancel occurred while the recall item was queued,
|
||
// we won't get here at all, but if it was cancelled while being executed, we
|
||
// might end up here with some bad workHr returned by the Mover code
|
||
if ((S_OK != workHr) && (S_OK != pSession->IsCanceling())) {
|
||
// Tell the session how things went if they didn't go well.
|
||
(void) pSession->ProcessHr(jobPhase, 0, 0, workHr);
|
||
}
|
||
}WsbCatch(hr);
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::DoFsaWork"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
return(hr);
|
||
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::MountMedia(
|
||
IHsmRecallItem *pWorkItem,
|
||
GUID mediaToMount,
|
||
BOOL bShortWait
|
||
)
|
||
|
||
/*++
|
||
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
GUID l_MediaToMount = mediaToMount;
|
||
CComPtr<IRmsDrive> pDrive;
|
||
CWsbBstrPtr pMediaName;
|
||
DWORD dwOptions = RMS_NONE;
|
||
DWORD threadId;
|
||
CComPtr<IFsaPostIt> pFsaWorkItem;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::MountMedia"),OLESTR("Display Name = <%ls>"), (WCHAR *)m_MediaName);
|
||
try {
|
||
WsbAffirmHr(pWorkItem->GetFsaPostIt(&pFsaWorkItem));
|
||
WsbAffirmHr(pFsaWorkItem->GetThreadId(&threadId));
|
||
|
||
// If we're switching tapes, dismount the current one
|
||
if ((m_MountedMedia != l_MediaToMount) && (m_MountedMedia != GUID_NULL)) {
|
||
WsbAffirmHr(DismountMedia());
|
||
}
|
||
// Ask RMS for short timeout, both for Mount and Allocate
|
||
if (bShortWait) {
|
||
dwOptions |= RMS_SHORT_TIMEOUT;
|
||
}
|
||
dwOptions |= RMS_USE_MOUNT_NO_DEADLOCK;
|
||
|
||
if (m_MountedMedia != l_MediaToMount) {
|
||
ReportMediaProgress(HSM_JOB_MEDIA_STATE_MOUNTING, hr);
|
||
hr = m_pRmsServer->MountCartridge( l_MediaToMount, &pDrive, &m_pRmsCartridge, &m_pDataMover, dwOptions, threadId);
|
||
hr = TranslateRmsMountHr(hr);
|
||
//
|
||
// If failure is because cartridge is disabled, need to get media label to put in error.
|
||
//
|
||
if (hr == RMS_E_CARTRIDGE_DISABLED) {
|
||
|
||
// Since this is just to get label, if any of these functions fail,
|
||
// don't throw, error will simply have blank label.
|
||
//
|
||
CComPtr<IRmsCartridge> pMedia;
|
||
HRESULT hrName;
|
||
|
||
hrName = m_pRmsServer->FindCartridgeById(l_MediaToMount , &pMedia);
|
||
if (hrName == S_OK) {
|
||
pMedia->GetName(&pMediaName);
|
||
}
|
||
if ((hrName != S_OK) || ((WCHAR *)pMediaName == NULL)) {
|
||
// Cannot get media name - set to blanks
|
||
pMediaName = L"";
|
||
}
|
||
|
||
WsbThrow(hr);
|
||
}
|
||
|
||
WsbAffirmHr(hr);
|
||
m_MountedMedia = l_MediaToMount;
|
||
WsbTrace( OLESTR("Mount completed.\n") );
|
||
|
||
WsbAffirmHr(GetMediaParameters());
|
||
|
||
}
|
||
}WsbCatchAndDo(hr,
|
||
switch (hr){case HSM_E_STG_PL_NOT_CFGD:case HSM_E_STG_PL_INVALID:
|
||
FailJob(pWorkItem);
|
||
break;case RMS_E_CARTRIDGE_DISABLED:
|
||
WsbLogEvent(HSM_MESSAGE_MEDIA_DISABLED, 0, NULL, pMediaName, NULL);
|
||
break;
|
||
default:
|
||
break;}
|
||
);
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::MountMedia"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::GetSource(
|
||
IFsaPostIt *pFsaWorkItem,
|
||
OLECHAR **pSourceString
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function builds the Source file name
|
||
|
||
Arguments:
|
||
|
||
pFsaWorkItem - the item to be migrated
|
||
pSourceString - the Source file name.
|
||
|
||
Return Value:
|
||
|
||
S_OK
|
||
|
||
--*/ {
|
||
HRESULT hr = S_OK;
|
||
|
||
CComPtr<IFsaResource> pResource;
|
||
CWsbStringPtr tmpString;
|
||
CComPtr<IHsmSession> pSession;
|
||
CWsbStringPtr path;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::GetSource"),OLESTR(""));
|
||
try {
|
||
//
|
||
// Get the real session pointer from the IUnknown
|
||
//
|
||
WsbAffirmHr(pFsaWorkItem->GetSession(&pSession));
|
||
WsbAffirm(pSession != 0, E_POINTER);
|
||
|
||
// First get the name of the resource from the session
|
||
WsbAffirmHr(pSession->GetResource(&pResource));
|
||
WsbAffirmHr(pFsaWorkItem->GetPath(&path, 0));
|
||
|
||
tmpString.Alloc(1000);
|
||
WsbAffirmHr(pResource->GetPath(&tmpString, 0));
|
||
tmpString.Append(&(path[1]));
|
||
// tmpString.Prepend(OLESTR("\\\\?\\"));
|
||
WsbAffirmHr(tmpString.GiveTo(pSourceString));
|
||
|
||
}WsbCatch(hr);
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::GetSource"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::GetScanItem(
|
||
IFsaPostIt *pFsaWorkItem,
|
||
IFsaScanItem ** ppIFsaScanItem
|
||
)
|
||
{
|
||
HRESULT hr = S_OK;
|
||
CWsbStringPtr path;
|
||
CComPtr<IHsmSession> pSession;
|
||
CComPtr<IFsaResource> pFsaResource;
|
||
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::GetScanItem"),OLESTR(""));
|
||
|
||
try {
|
||
WsbAffirmPointer(ppIFsaScanItem);
|
||
WsbAffirm(!*ppIFsaScanItem, E_INVALIDARG);
|
||
WsbAffirmHr(pFsaWorkItem->GetSession(&pSession));
|
||
WsbAffirmHr(pSession->GetResource(&pFsaResource));
|
||
WsbAffirmHr(pFsaWorkItem->GetPath(&path, 0));
|
||
WsbAffirmHr(pFsaResource->FindFirst(path, pSession, ppIFsaScanItem));
|
||
|
||
}WsbCatch (hr)
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::GetScanItem"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
return( hr );
|
||
}
|
||
|
||
|
||
DWORD HsmRecallQueueThread(
|
||
void *pVoid
|
||
)
|
||
|
||
/*++
|
||
|
||
|
||
--*/ {
|
||
HRESULT hr;
|
||
|
||
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||
hr = ((CHsmRecallQueue*) pVoid)->DoWork();
|
||
|
||
CoUninitialize();
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::SetState(
|
||
IN HSM_JOB_STATE state,
|
||
IN HSM_JOB_PHASE phase,
|
||
IN IHsmSession * pSession
|
||
)
|
||
|
||
/*++
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
BOOL bLog = TRUE;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue:SetState"), OLESTR("state = <%ls>"), JobStateAsString( state ) );
|
||
|
||
try {
|
||
//
|
||
// Change the state and report the change to the session. Unless the current state is
|
||
// failed then leave it failed. Is is necessary because when this guy fails, it will
|
||
// cancel all sessions so that no more work is sent in and so we will skip any queued work.
|
||
// If the current state is failed, we don't need to spit out the failed message every time,
|
||
// so we send ProcessState a false fullmessage unless the state is cancelled.
|
||
//
|
||
WsbAffirmHr(pSession->ProcessState(phase, state, m_CurrentPath, TRUE));
|
||
|
||
}WsbCatch(hr);
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::SetState"), OLESTR("hr = <%ls> "), WsbHrAsString(hr));
|
||
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::Cancel(
|
||
IN HSM_JOB_PHASE jobPhase,
|
||
IN IHsmSession *pSession
|
||
)
|
||
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
CHsmRecallQueue::Cancel().
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
UNREFERENCED_PARAMETER(pSession);
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::Cancel"), OLESTR(""));
|
||
|
||
(void)SetState(HSM_JOB_STATE_CANCELLING, jobPhase, pSession);
|
||
|
||
try {
|
||
//
|
||
// This needs to be prepended and the queue emptied out!
|
||
//
|
||
CComPtr<IHsmRecallItem> pWorkItem;
|
||
CComPtr<IFsaPostIt> pFsaWorkItem;
|
||
WsbAffirmHr(m_pHsmServerCreate->CreateInstance(CLSID_CHsmRecallItem, IID_IHsmRecallItem,
|
||
(void **)&pWorkItem));
|
||
//
|
||
// Create the minimal postit needed to contain the session so that DoWork
|
||
// can retrieve it from the work item.
|
||
// TBD: make pSession a member of CHsmRecallItem, so that we don't need
|
||
// to keep obtaining it via the IFsaPostIt. Also it saves us the trouble
|
||
// of creating a dummy FsaPostIt here.
|
||
//
|
||
WsbAffirmHr(m_pHsmServerCreate->CreateInstance(CLSID_CFsaPostIt, IID_IFsaPostIt,
|
||
(void **)&pFsaWorkItem));
|
||
|
||
WsbAffirmHr(pWorkItem->SetWorkType(HSM_WORK_ITEM_MOVER_CANCELLED));
|
||
WsbAffirmHr(pWorkItem->SetJobPhase(jobPhase));
|
||
WsbAffirmHr(pWorkItem->SetFsaPostIt(pFsaWorkItem));
|
||
WsbAffirmHr(pFsaWorkItem->SetSession(pSession));
|
||
//
|
||
// Our work item is ready now, ship it
|
||
//
|
||
WsbAffirmHr(m_pWorkToDo->Prepend(pWorkItem));
|
||
}WsbCatch(hr);
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::Cancel"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::FailJob(
|
||
IHsmRecallItem *pWorkItem
|
||
)
|
||
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
CHsmRecallQueue::FailJob().
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
CComPtr<IHsmSession> pSession;
|
||
CComPtr<IFsaPostIt> pFsaWorkItem;
|
||
HSM_JOB_PHASE jobPhase;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::FailJob"), OLESTR(""));
|
||
try {
|
||
//
|
||
// Set our state to failed and then cancel all work
|
||
//
|
||
WsbAffirmHr(pWorkItem->GetFsaPostIt(&pFsaWorkItem));
|
||
WsbAffirmHr(pFsaWorkItem->GetSession(&pSession));
|
||
WsbAffirmHr(pWorkItem->GetJobPhase(&jobPhase));
|
||
|
||
WsbAffirmHr(SetState(HSM_JOB_STATE_FAILED, jobPhase, pSession));
|
||
if (pSession != 0) {
|
||
WsbAffirmHr(pSession->Cancel( HSM_JOB_PHASE_ALL ));
|
||
}
|
||
|
||
}WsbCatch(hr);
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::FailJob"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
|
||
return(hr);
|
||
}
|
||
|
||
|
||
void
|
||
CHsmRecallQueue::ReportMediaProgress(
|
||
HSM_JOB_MEDIA_STATE state,
|
||
HRESULT /*status*/
|
||
)
|
||
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
CHsmRecallQueue::ReportMediaProgress().
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
CWsbStringPtr mediaName;
|
||
HSM_JOB_MEDIA_TYPE mediaType = HSM_JOB_MEDIA_TYPE_UNKNOWN;
|
||
|
||
UNREFERENCED_PARAMETER(state);
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::ReportMediaProgress"), OLESTR(""));
|
||
|
||
//
|
||
// TBD : we have to figure out a way to report media progress!
|
||
// Without the session pointer this is tough..
|
||
//
|
||
// Report Progress but we don't really care if it succeeds.
|
||
// hr = m_pSession->ProcessMediaState(m_JobPhase, state, m_MediaName, m_MediaType, 0);
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::ReportMediaProgress"), OLESTR("hr = <%ls>"), WsbHrAsString(hr) );
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::GetMediaParameters( void )
|
||
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
CHsmRecallQueue::GetMediaParameters
|
||
|
||
--*/ {
|
||
HRESULT hr = S_OK;
|
||
LONG rmsCartridgeType;
|
||
CWsbBstrPtr barCode;
|
||
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::GetMediaParameters"), OLESTR(""));
|
||
try {
|
||
//
|
||
// Get some information about the media
|
||
//
|
||
WsbAffirmHr(m_pDataMover->GetLargestFreeSpace( &m_MediaFreeSpace, &m_MediaCapacity ));
|
||
WsbAffirmHr(m_pRmsCartridge->GetType( &rmsCartridgeType ));
|
||
WsbAffirmHr(ConvertRmsCartridgeType(rmsCartridgeType, &m_MediaType));
|
||
WsbAffirmHr(m_pRmsCartridge->GetName(&barCode));
|
||
WsbAffirmHr(CoFileTimeNow(&m_MediaUpdate));
|
||
m_MediaBarCode = barCode;
|
||
}WsbCatch(hr);
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::GetMediaParameters"), OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::DismountMedia( BOOL bNoDelay)
|
||
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
CHsmRecallQueue::DismountMedia
|
||
|
||
--*/ {
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::DismountMedia"), OLESTR(""));
|
||
try {
|
||
if ((m_pRmsCartridge != 0) && (m_MountedMedia != GUID_NULL)) {
|
||
//
|
||
// End the session with the data mover. If this doesn't work, report
|
||
// the problem but continue with the dismount.
|
||
//
|
||
|
||
//
|
||
// Tell the session that we are dismounting media. Ignore any problems
|
||
// with the reporting
|
||
//
|
||
(void )ReportMediaProgress(HSM_JOB_MEDIA_STATE_DISMOUNTING, S_OK);
|
||
|
||
//
|
||
// Dismount the cartridge and report progress
|
||
//
|
||
|
||
// !!! IMPORTANT NOTE !!!
|
||
//
|
||
// Must free Rms resources used before dismounting...
|
||
//
|
||
m_pRmsCartridge = 0;
|
||
m_pDataMover = 0;
|
||
|
||
DWORD dwOptions = RMS_NONE;
|
||
if (bNoDelay) {
|
||
dwOptions |= RMS_DISMOUNT_DEFERRED_ONLY;
|
||
}
|
||
hr = m_pRmsServer->DismountCartridge(m_MountedMedia, dwOptions);
|
||
(void) ReportMediaProgress(HSM_JOB_MEDIA_STATE_DISMOUNTED, hr);
|
||
|
||
//
|
||
// Clear out the knowledge of media that was just dismounted
|
||
//
|
||
WsbAffirmHr(UnsetMediaInfo());
|
||
|
||
WsbAffirmHr(hr);
|
||
WsbTrace( OLESTR("Dismount completed OK.\n") );
|
||
} else {
|
||
WsbTrace( OLESTR("There is no media to dismount.\n") );
|
||
}
|
||
}WsbCatch(hr);
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::DismountMedia"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::ConvertRmsCartridgeType(
|
||
LONG rmsCartridgeType,
|
||
HSM_JOB_MEDIA_TYPE *pMediaType
|
||
)
|
||
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
CHsmRecallQueue::ConvertRmsCartridgeType
|
||
|
||
--*/ {
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::ConvertRmsCartridgeType"), OLESTR(""));
|
||
try {
|
||
|
||
WsbAssert(0 != pMediaType, E_POINTER);
|
||
|
||
switch (rmsCartridgeType) {
|
||
case RmsMedia8mm:
|
||
case RmsMedia4mm:
|
||
case RmsMediaDLT:
|
||
case RmsMediaTape:
|
||
*pMediaType = HSM_JOB_MEDIA_TYPE_TAPE;
|
||
break;
|
||
case RmsMediaOptical:
|
||
case RmsMediaMO35:
|
||
case RmsMediaWORM:
|
||
case RmsMediaCDR:
|
||
case RmsMediaDVD:
|
||
*pMediaType = HSM_JOB_MEDIA_TYPE_OPTICAL;
|
||
break;
|
||
case RmsMediaDisk:
|
||
*pMediaType = HSM_JOB_MEDIA_TYPE_REMOVABLE_MAG;
|
||
break;
|
||
case RmsMediaFixed:
|
||
*pMediaType = HSM_JOB_MEDIA_TYPE_FIXED_MAG;
|
||
break;
|
||
case RmsMediaUnknown:default:
|
||
*pMediaType = HSM_JOB_MEDIA_TYPE_UNKNOWN;
|
||
break;
|
||
}
|
||
}WsbCatch( hr );
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::ConvertRmsCartridgeType"), OLESTR("hr = <%ls>"),
|
||
WsbHrAsString(hr));
|
||
return(hr);
|
||
}
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::MarkWorkItemAsDone(IN IHsmSession *pSession,
|
||
IN HSM_JOB_PHASE jobPhase)
|
||
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
CHsmRecallQueue::MarkWorkItemAsDone
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::MarkWorkItemAsDone"), OLESTR(""));
|
||
try {
|
||
// Create a work item and append it to the work queue to
|
||
// indicate that the job is done
|
||
CComPtr<IHsmRecallItem> pWorkItem;
|
||
CComPtr<IFsaPostIt> pFsaWorkItem;
|
||
WsbAffirmHr(m_pHsmServerCreate->CreateInstance(CLSID_CHsmRecallItem, IID_IHsmRecallItem,
|
||
(void **)&pWorkItem));
|
||
|
||
//
|
||
// Create the minimal postit needed to contain the session so that DoWork
|
||
// can retrieve it from the work item.
|
||
// TBD: make pSession a member of CHsmRecallItem, so that we don't need
|
||
// to keep obtaining it via the IFsaPostIt. Also it saves us the trouble
|
||
// of creating a dummy FsaPostIt here.
|
||
//
|
||
WsbAffirmHr(m_pHsmServerCreate->CreateInstance(CLSID_CFsaPostIt, IID_IFsaPostIt,
|
||
(void **)&pFsaWorkItem));
|
||
|
||
WsbAffirmHr(pWorkItem->SetWorkType(HSM_WORK_ITEM_FSA_DONE));
|
||
WsbAffirmHr(pWorkItem->SetJobPhase(jobPhase));
|
||
WsbAffirmHr(pWorkItem->SetFsaPostIt(pFsaWorkItem));
|
||
WsbAffirmHr(pFsaWorkItem->SetSession(pSession));
|
||
//
|
||
// Our work item is ready now, ship it
|
||
//
|
||
WsbAffirmHr(m_pWorkToDo->Append(pWorkItem));
|
||
|
||
}WsbCatch(hr);
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::MarkWorkItemAsDone"), OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::CheckRegistry(void)
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::CheckRegistry"), OLESTR(""));
|
||
|
||
try {
|
||
// Check for change to number of errors to allow before cancelling
|
||
// a job
|
||
WsbAffirmHr(WsbRegistryValueUlongAsString(NULL, HSM_ENGINE_REGISTRY_STRING, HSM_JOB_ABORT_CONSECUTIVE_ERRORS,
|
||
&m_JobAbortMaxConsecutiveErrors));
|
||
WsbTrace(OLESTR("CHsmRecallQueue::CheckRegistry: m_JobAbortMaxConsecutiveErrors = %lu\n"),
|
||
m_JobAbortMaxConsecutiveErrors);
|
||
WsbAffirmHr(WsbRegistryValueUlongAsString(NULL, HSM_ENGINE_REGISTRY_STRING, HSM_JOB_ABORT_TOTAL_ERRORS,
|
||
&m_JobAbortMaxTotalErrors));
|
||
WsbTrace(OLESTR("CHsmRecallQueue::CheckRegistry: m_JobAbortMaxTotalErrors = %lu\n"),
|
||
m_JobAbortMaxTotalErrors);
|
||
|
||
|
||
}WsbCatch( hr );
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::CheckRegistry"), OLESTR("hr = <%ls>"),
|
||
WsbHrAsString(hr));
|
||
|
||
return( hr );
|
||
}
|
||
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::TranslateRmsMountHr(
|
||
HRESULT rmsMountHr
|
||
)
|
||
|
||
/*++
|
||
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::TranslateRmsMountHr"),OLESTR("rms hr = <%ls>"), WsbHrAsString(rmsMountHr));
|
||
try {
|
||
switch (rmsMountHr) {
|
||
case S_OK:
|
||
hr = S_OK;
|
||
ReportMediaProgress(HSM_JOB_MEDIA_STATE_MOUNTED, hr);
|
||
break;
|
||
case RMS_E_MEDIASET_NOT_FOUND:
|
||
if (m_RmsMediaSetId == GUID_NULL) {
|
||
hr = HSM_E_STG_PL_NOT_CFGD;
|
||
} else {
|
||
hr = HSM_E_STG_PL_INVALID;
|
||
}
|
||
ReportMediaProgress(HSM_JOB_MEDIA_STATE_UNAVAILABLE, hr);
|
||
break;
|
||
case RMS_E_SCRATCH_NOT_FOUND:
|
||
hr = HSM_E_NO_MORE_MEDIA;
|
||
ReportMediaProgress(HSM_JOB_MEDIA_STATE_UNAVAILABLE, hr);
|
||
break;
|
||
case RMS_E_CARTRIDGE_UNAVAILABLE:
|
||
case RMS_E_RESOURCE_UNAVAILABLE:
|
||
case RMS_E_DRIVE_UNAVAILABLE:
|
||
case RMS_E_LIBRARY_UNAVAILABLE:
|
||
hr = HSM_E_MEDIA_NOT_AVAILABLE;
|
||
ReportMediaProgress(HSM_JOB_MEDIA_STATE_UNAVAILABLE, hr);
|
||
break;
|
||
case RMS_E_CARTRIDGE_BUSY:
|
||
case RMS_E_RESOURCE_BUSY:
|
||
case RMS_E_DRIVE_BUSY:
|
||
hr = HSM_E_MEDIA_BUSY;
|
||
ReportMediaProgress(HSM_JOB_MEDIA_STATE_BUSY, hr);
|
||
break;
|
||
case RMS_E_CARTRIDGE_NOT_FOUND:
|
||
case RMS_E_CARTRIDGE_DISABLED:
|
||
case RMS_E_TIMEOUT:
|
||
hr = rmsMountHr;
|
||
ReportMediaProgress(HSM_JOB_MEDIA_STATE_UNAVAILABLE, hr);
|
||
break;
|
||
default:
|
||
hr = rmsMountHr;
|
||
ReportMediaProgress(HSM_JOB_MEDIA_STATE_UNAVAILABLE, hr);
|
||
break;
|
||
}
|
||
}WsbCatch( hr );
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::TranslateRmsMountHr"),
|
||
OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
return(hr);
|
||
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::Remove(
|
||
IHsmRecallItem *pWorkItem
|
||
)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IHsmFsaTskMgr::Remove
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::Remove"),OLESTR(""));
|
||
try {
|
||
//
|
||
// Remove the item from the queue
|
||
//
|
||
(void)m_pWorkToDo->RemoveAndRelease(pWorkItem);
|
||
}WsbCatch (hr);
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::Remove"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::ChangeSysState(
|
||
IN OUT HSM_SYSTEM_STATE* pSysState
|
||
)
|
||
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IHsmSystemState::ChangeSysState().
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::ChangeSysState"), OLESTR(""));
|
||
|
||
try {
|
||
|
||
if (pSysState->State & HSM_STATE_SUSPEND) {
|
||
// Should have already been paused via the job}else if (pSysState->State & HSM_STATE_RESUME){
|
||
// Should have already been resumed via the job}else if (pSysState->State & HSM_STATE_SHUTDOWN){
|
||
|
||
// Release the thread (we assume it has been stopped already)
|
||
if (m_WorkerThread) {
|
||
CloseHandle(m_WorkerThread);
|
||
m_WorkerThread = 0;
|
||
}
|
||
|
||
if (m_pDataMover) {
|
||
//
|
||
// Cancel any active I/O
|
||
//
|
||
(void) m_pDataMover->Cancel();
|
||
}
|
||
/* TBD
|
||
// If Session is valid - unadvise and free session, otherwise, just try to
|
||
// dismount media if it is mounted (which we don't know at this point)
|
||
// Best effort dismount, no error checking so following resources will get released.
|
||
if (m_pSession != 0) {
|
||
EndSessions(FALSE, TRUE);
|
||
} else {
|
||
(void) DismountMedia(TRUE);
|
||
}
|
||
*/
|
||
(void) DismountMedia(TRUE);
|
||
}
|
||
|
||
}WsbCatch(hr);
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::ChangeSysState"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::EndRecallSession(
|
||
IN IHsmRecallItem *pWorkItem,
|
||
IN BOOL cancelled
|
||
)
|
||
{
|
||
HRESULT hr = S_OK;
|
||
CComPtr<IFsaPostIt> pFsaWorkItem;
|
||
DWORD stateCookie;
|
||
DWORD eventCookie;
|
||
|
||
ULONG refCount;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::EndRecallSession"),OLESTR(""));
|
||
try {
|
||
HRESULT dismountHr = S_OK;
|
||
|
||
CComPtr<IConnectionPointContainer> pCPC;
|
||
CComPtr<IConnectionPoint> pCP;
|
||
CComPtr<IHsmSession> pSession;
|
||
HSM_JOB_PHASE jobPhase;
|
||
//
|
||
// Get the session
|
||
//
|
||
WsbAffirmHr(pWorkItem->GetFsaPostIt(&pFsaWorkItem));
|
||
WsbAffirmHr(pFsaWorkItem->GetSession(&pSession));
|
||
WsbAffirmHr(pWorkItem->GetStateCookie(&stateCookie));
|
||
WsbAffirmHr(pWorkItem->GetEventCookie(&eventCookie));
|
||
WsbAffirmHr(pWorkItem->GetJobPhase(&jobPhase));
|
||
//
|
||
// Tell the session that we don't want to be advised anymore.
|
||
//
|
||
try {
|
||
WsbAffirmHr(pSession->QueryInterface(IID_IConnectionPointContainer, (void**) &pCPC));
|
||
WsbAffirmHr(pCPC->FindConnectionPoint(IID_IHsmSessionSinkEveryState, &pCP));
|
||
|
||
refCount = (((IUnknown *) (IHsmFsaTskMgr *) this)->AddRef()) - 1;
|
||
((IUnknown *) (IHsmFsaTskMgr *)this)->Release();
|
||
WsbTrace(OLESTR("REFCOUNT for CHsmRecallQueue before stateCookie UnAdvise: %ls \n"), WsbLongAsString((LONG) refCount));
|
||
|
||
WsbAffirmHr(pCP->Unadvise(stateCookie));
|
||
}WsbCatch( hr );
|
||
|
||
refCount = (((IUnknown *) (IHsmFsaTskMgr *) this)->AddRef()) - 1;
|
||
((IUnknown *) (IHsmFsaTskMgr *)this)->Release();
|
||
WsbTrace(OLESTR("REFCOUNT for CHsmRecallQueue after stateCookie UnAdvise: %ls \n"), WsbLongAsString((LONG) refCount));
|
||
|
||
pCPC = 0;
|
||
pCP = 0;
|
||
|
||
refCount = (((IUnknown *) (IHsmFsaTskMgr *) this)->AddRef()) - 1;
|
||
((IUnknown *) (IHsmFsaTskMgr *)this)->Release();
|
||
WsbTrace(OLESTR("REFCOUNT for CHsmRecallQueue before eventCookie UnAdvise: %ls \n"), WsbLongAsString((LONG) refCount));
|
||
|
||
try {
|
||
WsbAffirmHr(pSession->QueryInterface(IID_IConnectionPointContainer, (void**) &pCPC));
|
||
WsbAffirmHr(pCPC->FindConnectionPoint(IID_IHsmSessionSinkEveryEvent, &pCP));
|
||
WsbAffirmHr(pCP->Unadvise(eventCookie));
|
||
}WsbCatch( hr );
|
||
|
||
refCount = (((IUnknown *) (IHsmFsaTskMgr *) this)->AddRef()) - 1;
|
||
((IUnknown *) (IHsmFsaTskMgr *)this)->Release();
|
||
WsbTrace(OLESTR("REFCOUNT for CHsmRecallQueue after eventCookie UnAdvise: %ls \n"), WsbLongAsString((LONG) refCount));
|
||
|
||
pCPC = 0;
|
||
pCP = 0;
|
||
|
||
WsbTrace( OLESTR("Telling Session Data mover is done\n") );
|
||
if (cancelled) {
|
||
(void)SetState(HSM_JOB_STATE_DONE, jobPhase, pSession);
|
||
} else {
|
||
(void)SetState(HSM_JOB_STATE_CANCELLED, jobPhase, pSession);
|
||
}
|
||
pSession = 0;
|
||
WsbAffirmHr(hr);
|
||
}WsbCatch (hr);
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::EndRecallSession"),OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::UnsetMediaInfo( void )
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Sets the media data members back to their default (unset) values.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
S_OK: Ok.
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::UnsetMediaInfo"), OLESTR(""));
|
||
|
||
m_MediaId = GUID_NULL;
|
||
m_MountedMedia = GUID_NULL;
|
||
m_MediaType = HSM_JOB_MEDIA_TYPE_UNKNOWN;
|
||
m_MediaName = OLESTR("");
|
||
m_MediaBarCode = OLESTR("");
|
||
m_MediaFreeSpace = 0;
|
||
m_MediaCapacity = 0;
|
||
m_MediaReadOnly = FALSE;
|
||
m_MediaUpdate = WsbLLtoFT(0);
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::UnsetMediaInfo"), OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::GetMediaId (OUT GUID *mediaId)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Gets the media id for the queue
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
S_OK: Ok.
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::GetMediaId"), OLESTR(""));
|
||
*mediaId = m_MediaId;
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::GetMediaId"),OLESTR("hr = <%ls>, Id = <%ls>"),
|
||
WsbHrAsString(hr), WsbPtrToGuidAsString(mediaId));
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::SetMediaId (IN GUID *mediaId)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Sets the media id for the queue
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
S_OK: Ok.
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::SetMediaId"), OLESTR(""));
|
||
m_MediaId = *mediaId;
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::SetMediaId"),OLESTR("hr = <%ls>, Id = <%ls>"),
|
||
WsbHrAsString(hr), WsbPtrToGuidAsString(mediaId));
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::IsEmpty ( void )
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Checks if the queue is empty
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
S_OK: Queue is empty
|
||
S_FALSE: Queue is non-empty
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr;
|
||
hr = m_pWorkToDo->IsEmpty();
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRecallQueue::FindRecallItemToCancel(
|
||
IHsmRecallItem *pWorkItem,
|
||
IHsmRecallItem **pWorkItemToCancel
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Pulls the work item that needs to be cancelled
|
||
indicated by pWorkItem and returns it
|
||
(by matching the pSession pointer)
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
|
||
--*/
|
||
{
|
||
CComPtr<IFsaPostIt> pFsaWorkItem;
|
||
CComPtr<IHsmSession> pSession;
|
||
CComPtr<IHsmSession> pWorkSession;
|
||
HRESULT hr;
|
||
ULONG index = 0;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRecallQueue::FindRecallItemToCancel"), OLESTR(""));
|
||
|
||
pWorkItem->GetFsaPostIt(&pFsaWorkItem);
|
||
pFsaWorkItem->GetSession(&pSession);
|
||
pFsaWorkItem = 0;
|
||
do {
|
||
hr = m_pWorkToDo->At(index, IID_IHsmRecallItem, (void **)pWorkItemToCancel);
|
||
if (S_OK == hr) {
|
||
(*pWorkItemToCancel)->GetFsaPostIt(&pFsaWorkItem);
|
||
pFsaWorkItem->GetSession(&pWorkSession);
|
||
if ((pWorkItem != (*pWorkItemToCancel)) && (pSession == pWorkSession)) {
|
||
WsbTrace(OLESTR("CHsmRecallQueue::FindRecallItemToCancel: Found item to cancel, pSession = %p\n"), pSession);
|
||
break;
|
||
}
|
||
(*pWorkItemToCancel)->Release();
|
||
(*pWorkItemToCancel) = 0;
|
||
pWorkSession = 0;
|
||
pFsaWorkItem = 0;
|
||
}
|
||
index++;
|
||
} while (S_OK == hr);
|
||
|
||
WsbTraceOut(OLESTR("CHsmRecallQueue::FindRecallItemToCancel"), OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
||
|
||
return hr;
|
||
}
|