/*++ © 1998 Seagate Software, Inc. All rights reserved. Module Name: hsmsess.cpp Abstract: This module contains the session component. The session is the collator of information for the work being done on a resource (for a job, demand recall, truncate, ...). Author: Chuck Bardeen [cbardeen] 18-Feb-1997 Revision History: --*/ #include "stdafx.h" #include "wsb.h" #include "fsa.h" #include "job.h" #include "HsmSess.h" #define WSB_TRACE_IS WSB_TRACE_BIT_JOB static USHORT iCount = 0; HRESULT CHsmSession::AdviseOfEvent( IN HSM_JOB_PHASE phase, IN HSM_JOB_EVENT event ) /*++ --*/ { HRESULT hr = S_OK; HRESULT hr2 = S_OK; CONNECTDATA pConnectData; CComPtr pCP; CComPtr pCPC; CComPtr pConnection; CComPtr pSink; try { // Tell everyone the new state of the session. WsbAffirmHr(((IUnknown*)(IHsmSession*) this)->QueryInterface(IID_IConnectionPointContainer, (void**) &pCPC)); WsbAffirmHr(pCPC->FindConnectionPoint(IID_IHsmSessionSinkEveryEvent, &pCP)); WsbAffirmHr(pCP->EnumConnections(&pConnection)); while(pConnection->Next(1, &pConnectData, 0) == S_OK) { // We don't care if the sink has problems (it's their problem). try { WsbAffirmHr((pConnectData.pUnk)->QueryInterface(IID_IHsmSessionSinkEveryEvent, (void**) &pSink)); WsbAffirmHr(pSink->ProcessSessionEvent(((IHsmSession*) this), phase, event)); } WsbCatchAndDo(hr2, ProcessHr(phase, __FILE__, __LINE__, hr2);); WsbAffirmHr((pConnectData.pUnk)->Release()); pSink=0; } } WsbCatch(hr); return(hr); } HRESULT CHsmSession::AdviseOfItem( IN IHsmPhase* pPhase, IN IFsaScanItem* pScanItem, IN HRESULT hrItem, IN IHsmSessionTotals* pSessionTotals ) /*++ --*/ { HRESULT hr = S_OK; HRESULT hr2 = S_OK; CONNECTDATA pConnectData; FILETIME currentTime; LONGLONG advisedInterval; CComPtr pCP; CComPtr pCPC; CComPtr pConnection; CComPtr pSink; CComPtr pSink2; HSM_JOB_PHASE phase; try { // For the item there are two ways to tell, so both need to be checked. // Tell those who want to know about every single file. WsbAffirmHr(((IUnknown*)(IHsmSession*) this)->QueryInterface(IID_IConnectionPointContainer, (void**) &pCPC)); WsbAffirmHr(pCPC->FindConnectionPoint(IID_IHsmSessionSinkEveryItem, &pCP)); WsbAffirmHr(pCP->EnumConnections(&pConnection)); while (pConnection->Next(1, &pConnectData, 0) == S_OK) { // We don't care if the sink has problems (it's their problem). try { WsbAffirmHr((pConnectData.pUnk)->QueryInterface(IID_IHsmSessionSinkEveryItem, (void**) &pSink)); WsbAffirmHr(pSink->ProcessSessionItem(((IHsmSession*) this), pPhase, pScanItem, hrItem, pSessionTotals)); } WsbCatchAndDo(hr2, pPhase->GetPhase(&phase); ProcessHr(phase, __FILE__, __LINE__, hr2);); WsbAffirmHr((pConnectData.pUnk)->Release()); pSink=0; } pCPC = 0; pCP = 0; pConnection = 0; // If we haven't told them withing the interval, then tell those who want to know about some of the files. GetSystemTimeAsFileTime(¤tTime); advisedInterval = ((currentTime.dwHighDateTime - m_lastAdviseFile.dwHighDateTime) << 32) + (currentTime.dwLowDateTime - m_lastAdviseFile.dwLowDateTime); if ((advisedInterval) > m_adviseInterval) { m_lastAdviseFile = currentTime; WsbAffirmHr(((IHsmSession*) this)->QueryInterface(IID_IConnectionPointContainer, (void**) &pCPC)); WsbAffirmHr(pCPC->FindConnectionPoint(IID_IHsmSessionSinkSomeItems, &pCP)); WsbAffirmHr(pCP->EnumConnections(&pConnection)); while(pConnection->Next(1, &pConnectData, 0) == S_OK) { // We don't care if the sink has problems (it's their problem). try { WsbAffirmHr((pConnectData.pUnk)->QueryInterface(IID_IHsmSessionSinkSomeItems, (void**) &pSink2)); WsbAffirmHr(pSink2->ProcessSessionItem(((IHsmSession*) this), pPhase, pScanItem, hrItem, pSessionTotals)); } WsbCatchAndDo(hr2, pPhase->GetPhase(&phase); ProcessHr(phase, __FILE__, __LINE__, hr2);); WsbAffirmHr((pConnectData.pUnk)->Release()); pSink2=0; } } } WsbCatch(hr); return(hr); } HRESULT CHsmSession::AdviseOfMediaState( IN IHsmPhase* pPhase, IN HSM_JOB_MEDIA_STATE state, IN OLECHAR* mediaName, IN HSM_JOB_MEDIA_TYPE mediaType, IN ULONG time ) /*++ --*/ { HRESULT hr = S_OK; HRESULT hr2 = S_OK; CONNECTDATA pConnectData; CComPtr pCP; CComPtr pCPC; CComPtr pConnection; CComPtr pSink; HSM_JOB_PHASE phase; try { // Tell everyone the new media state for the session. WsbAffirmHr(((IHsmSession*) this)->QueryInterface(IID_IConnectionPointContainer, (void**) &pCPC)); WsbAffirmHr(pCPC->FindConnectionPoint(IID_IHsmSessionSinkEveryMediaState, &pCP)); WsbAffirmHr(pCP->EnumConnections(&pConnection)); while(pConnection->Next(1, &pConnectData, 0) == S_OK) { // We don't care if the sink has problems (it's their problem). try { WsbAffirmHr((pConnectData.pUnk)->QueryInterface(IID_IHsmSessionSinkEveryMediaState, (void**) &pSink)); WsbAffirmHr(pSink->ProcessSessionMediaState(((IHsmSession*) this), pPhase, state, mediaName, mediaType, time)); } WsbCatchAndDo(hr2, pPhase->GetPhase(&phase); ProcessHr(phase, __FILE__, __LINE__, hr2);); WsbAffirmHr((pConnectData.pUnk)->Release()); pSink=0; } } WsbCatch(hr); return(hr); } HRESULT CHsmSession::AdviseOfPriority( IN IHsmPhase* pPhase ) /*++ --*/ { HRESULT hr = S_OK; HRESULT hr2 = S_OK; CONNECTDATA pConnectData; CComPtr pCP; CComPtr pCPC; CComPtr pConnection; CComPtr pSink; HSM_JOB_PHASE phase; try { // Tell everyone the new priority of a phase of the session. WsbAffirmHr(((IHsmSession*) this)->QueryInterface(IID_IConnectionPointContainer, (void**) &pCPC)); WsbAffirmHr(pCPC->FindConnectionPoint(IID_IHsmSessionSinkEveryPriority, &pCP)); WsbAffirmHr(pCP->EnumConnections(&pConnection)); while(pConnection->Next(1, &pConnectData, 0) == S_OK) { // We don't care if the sink has problems (it's their problem). try { WsbAffirmHr((pConnectData.pUnk)->QueryInterface(IID_IHsmSessionSinkEveryPriority, (void**) &pSink)); WsbAffirmHr(pSink->ProcessSessionPriority(((IHsmSession*) this), pPhase)); } WsbCatchAndDo(hr2, pPhase->GetPhase(&phase); ProcessHr(phase, __FILE__, __LINE__, hr2);); WsbAffirmHr((pConnectData.pUnk)->Release()); pSink=0; } } WsbCatch(hr); return(hr); } HRESULT CHsmSession::AdviseOfState( IN IHsmPhase* pPhase, IN OLECHAR* currentPath ) /*++ --*/ { HRESULT hr = S_OK; HRESULT hr2 = S_OK; CONNECTDATA pConnectData; CComPtr pCP; CComPtr pCPC; CComPtr pConnection; CComPtr pSink; HSM_JOB_PHASE phase; try { // Tell everyone the new state of the session. WsbAffirmHr(((IHsmSession*) this)->QueryInterface(IID_IConnectionPointContainer, (void**) &pCPC)); WsbAffirmHr(pCPC->FindConnectionPoint(IID_IHsmSessionSinkEveryState, &pCP)); WsbAffirmHr(pCP->EnumConnections(&pConnection)); while(pConnection->Next(1, &pConnectData, 0) == S_OK) { // We don't care if the sink has problems (it's their problem). try { WsbAffirmHr((pConnectData.pUnk)->QueryInterface(IID_IHsmSessionSinkEveryState, (void**) &pSink)); WsbAffirmHr(pSink->ProcessSessionState(((IHsmSession*) this), pPhase, currentPath)); } WsbCatchAndDo(hr2, pPhase->GetPhase(&phase); ProcessHr(phase, __FILE__, __LINE__, hr2);); WsbAffirmHr((pConnectData.pUnk)->Release()); pSink=0; } } WsbCatch(hr); return(hr); } HRESULT CHsmSession::Cancel( IN HSM_JOB_PHASE phase ) /*++ Implements: IHsmSession::Cancel(). --*/ { return(AdviseOfEvent(phase, HSM_JOB_EVENT_CANCEL)); } HRESULT CHsmSession::EnumPhases( IN IWsbEnum** ppEnum ) /*++ Implements: IHsmSession::EnumPhases(). --*/ { HRESULT hr = S_OK; try { WsbAssert(0 != ppEnum, E_POINTER); WsbAffirmHr(m_pPhases->Enum(ppEnum)); } WsbCatch(hr); return(hr); } HRESULT CHsmSession::EnumTotals( IN IWsbEnum** ppEnum ) /*++ Implements: IHsmSession::EnumTotals(). --*/ { HRESULT hr = S_OK; try { WsbAssert(0 != ppEnum, E_POINTER); WsbAffirmHr(m_pTotals->Enum(ppEnum)); } WsbCatch(hr); return(hr); } HRESULT CHsmSession::FinalConstruct( void ) /*++ Implements: CComObjectRoot::FinalConstruct(). --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CHsmSession::FinalConstruct"), OLESTR("this = %p"), this); try { WsbAffirmHr(CWsbObject::FinalConstruct()); m_hsmId = GUID_NULL; m_adviseInterval = 10000; m_runId = 0; m_subRunId = 0; m_state = HSM_JOB_STATE_IDLE; m_activePhases = 0; m_lastAdviseFile.dwHighDateTime = 0; m_lastAdviseFile.dwLowDateTime = 0; m_logControl = HSM_JOB_LOG_NORMAL; m_isCanceling = FALSE; // Each instance should have its own unique identifier. WsbAffirmHr(CoCreateGuid(&m_id)); // Create the phase and totals collections. WsbAffirmHr(CoCreateInstance(CLSID_CWsbOrderedCollection, 0, CLSCTX_ALL, IID_IWsbCollection, (void**) &m_pPhases)); WsbAffirmHr(CoCreateInstance(CLSID_CWsbOrderedCollection, 0, CLSCTX_ALL, IID_IWsbCollection, (void**) &m_pTotals)); } WsbCatch(hr); iCount++; WsbTraceOut(OLESTR("CHsmSession::FinalConstruct"), OLESTR("hr = <%ls>, count is <%d>"), WsbHrAsString(hr), iCount); return(hr); } void CHsmSession::FinalRelease( void ) /*++ Implements: CHsmSession::FinalRelease(). --*/ { WsbTraceIn(OLESTR("CHsmSession::FinalRelease"), OLESTR("this = %p"), this); CWsbObject::FinalRelease(); iCount--; WsbTraceOut(OLESTR("CHsmSession::FinalRelease"), OLESTR("Count is <%d>"), iCount); } HRESULT CHsmSession::GetAdviseInterval( OUT LONGLONG* pInterval ) /*++ Implements: IHsmSession::GetAdviseInterval(). --*/ { HRESULT hr = S_OK; try { WsbAssert(0 != pInterval, E_POINTER); *pInterval = m_adviseInterval; } WsbCatch(hr); return(hr); } HRESULT CHsmSession::GetClassID( OUT CLSID* pClsid ) /*++ Implements: IPersist::GetClassID(). --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CHsmSession::GetClassID"), OLESTR("")); try { WsbAssert(0 != pClsid, E_POINTER); *pClsid = CLSID_CHsmSession; } WsbCatch(hr); WsbTraceOut(OLESTR("CHsmSession::GetClassID"), OLESTR("hr = <%ls>, CLSID = <%ls>"), WsbHrAsString(hr), WsbGuidAsString(*pClsid)); return(hr); } HRESULT CHsmSession::GetHsmId( OUT GUID* pId ) /*++ Implements: IHsmSession::GetHsmId(). --*/ { HRESULT hr = S_OK; try { WsbAssert(0 != pId, E_POINTER); *pId = m_hsmId; } WsbCatch(hr); return(hr); } HRESULT CHsmSession::GetIdentifier( OUT GUID* pId ) /*++ Implements: IHsmSession::GetIdentifier(). --*/ { HRESULT hr = S_OK; try { WsbAssert(0 != pId, E_POINTER); *pId = m_id; } WsbCatch(hr); return(hr); } HRESULT CHsmSession::GetJob( OUT IHsmJob** ppJob ) /*++ Implements: IHsmSession::GetJob(). --*/ { HRESULT hr = S_OK; try { WsbAssert(0 != ppJob, E_POINTER); *ppJob = m_pJob; if (m_pJob != 0) { m_pJob->AddRef(); } } WsbCatch(hr); return(hr); } HRESULT CHsmSession::GetName( OLECHAR** pName, ULONG bufferSize ) /*++ Implements: IHsmSession::GetName(). --*/ { HRESULT hr = S_OK; try { WsbAssert(0 != pName, E_POINTER); WsbAffirmHr(m_name.CopyTo(pName, bufferSize)); } WsbCatch(hr); return(hr); } HRESULT CHsmSession::GetResource( OUT IFsaResource** ppResource ) /*++ Implements: IHsmSession::GetResource(). --*/ { HRESULT hr = S_OK; try { WsbAssert(0 != ppResource, E_POINTER); *ppResource = m_pResource; if (m_pResource != 0) { m_pResource->AddRef(); } } WsbCatch(hr); return(hr); } HRESULT CHsmSession::GetRunId( OUT ULONG* pId ) /*++ Implements: IHsmSession::GetRunId(). --*/ { HRESULT hr = S_OK; try { WsbAssert(0 != pId, E_POINTER); *pId = m_runId; } WsbCatch(hr); return(hr); } HRESULT CHsmSession::GetSubRunId( OUT ULONG* pId ) /*++ Implements: IHsmSession::GetSubRunId(). --*/ { HRESULT hr = S_OK; try { WsbAssert(0 != pId, E_POINTER); *pId = m_subRunId; } WsbCatch(hr); return(hr); } HRESULT CHsmSession::GetSizeMax( OUT ULARGE_INTEGER* pSize ) /*++ Implements: IPersistStream::GetSizeMax(). --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CHsmSession::GetSizeMax"), OLESTR("")); pSize->QuadPart = 0; hr = E_NOTIMPL; WsbTraceOut(OLESTR("CHsmSession::GetSizeMax"), OLESTR("hr = <%ls>, Size = <%ls>"), WsbHrAsString(hr), WsbPtrToUliAsString(pSize)); return(hr); } HRESULT CHsmSession::Load( IN IStream* pStream ) /*++ Implements: IPersistStream::Load(). --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CHsmSession::Load"), OLESTR("")); try { WsbAssert(0 != pStream, E_POINTER); hr = E_NOTIMPL; } WsbCatch(hr); WsbTraceOut(OLESTR("CHsmSession::Load"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return(hr); } HRESULT CHsmSession::Pause( IN HSM_JOB_PHASE phase ) /*++ Implements: IHsmSession::Pause(). --*/ { return(AdviseOfEvent(phase, HSM_JOB_EVENT_PAUSE)); } HRESULT CHsmSession::ProcessEvent( IN HSM_JOB_PHASE phase, IN HSM_JOB_EVENT event ) /*++ Implements: IHsmSession::ProcessEvent(). --*/ { HRESULT hr = S_OK; HRESULT hr2 = S_OK; try { // Tell everyone about the new event, but don't return an error if this fails. try { WsbAffirmHr(AdviseOfEvent(phase, event)); } WsbCatchAndDo(hr2, ProcessHr(phase, __FILE__, __LINE__, hr2);); } WsbCatch(hr); return(hr); } HRESULT CHsmSession::ProcessHr( IN HSM_JOB_PHASE phase, IN CHAR* file, IN ULONG line, IN HRESULT inHr ) /*++ Implements: IHsmSession::ProcessHr(). --*/ { HRESULT hr = S_OK; CComPtr pEnum; CComPtr pPhasePriv; CComPtr pFoundPhasePriv; CWsbStringPtr phaseName; CWsbStringPtr resourceName; CWsbStringPtr fileName = file; UNREFERENCED_PARAMETER(line); try { if ((m_logControl & HSM_JOB_LOG_HR) != 0) { WsbAffirmHr(EnumPhases(&pEnum)); WsbAffirmHr(CoCreateInstance(CLSID_CHsmPhase, 0, CLSCTX_ALL, IID_IHsmPhasePriv, (void**) &pPhasePriv)); WsbAffirmHr(pPhasePriv->SetPhase(phase)); WsbAffirmHr(pEnum->Find(pPhasePriv, IID_IHsmPhasePriv, (void**) &pFoundPhasePriv)); WsbAffirmHr(pFoundPhasePriv->GetName(&phaseName, 0)); WsbAffirmHr(m_pResource->GetLogicalName(&resourceName, 0)); // If no file was specified, then don't display the file and line number. if ((0 == file) || (0 == *file)) { WsbLogEvent(JOB_MESSAGE_SESSION_ERROR, 0, NULL, (OLECHAR*) m_name, (OLECHAR*) phaseName, (OLECHAR*) resourceName, WsbHrAsString(inHr), NULL); } else { #ifdef DBG WsbLogEvent(JOB_MESSAGE_SESSION_INTERNALERROR, 0, NULL, (OLECHAR*) m_name, (OLECHAR*) phaseName, (OLECHAR*) resourceName, (OLECHAR*) fileName, WsbLongAsString(line), WsbHrAsString(inHr), NULL); #else WsbLogEvent(JOB_MESSAGE_SESSION_ERROR, 0, NULL, (OLECHAR*) m_name, (OLECHAR*) phaseName, (OLECHAR*) resourceName, WsbHrAsString(inHr), NULL); #endif } } } WsbCatch(hr); return(hr); } HRESULT CHsmSession::ProcessItem( IN HSM_JOB_PHASE phase, IN HSM_JOB_ACTION action, IN IFsaScanItem* pScanItem, IN HRESULT hrItem ) /*++ Implements: IHsmSession::ProcessItem(). --*/ { HRESULT hr = S_OK; HRESULT hr2 = S_OK; CWsbStringPtr itemPath; CWsbStringPtr phaseName; CWsbStringPtr resourceName; CComPtr pEnum; CComPtr pPhasePriv; CComPtr pFoundPhasePriv; CComPtr pFoundPhase; CComPtr pTotalsPriv; CComPtr pFoundTotalsPriv; CComPtr pFoundTotals; try { // Update the phase. WsbAffirmHr(EnumPhases(&pEnum)); WsbAffirmHr(CoCreateInstance(CLSID_CHsmPhase, 0, CLSCTX_ALL, IID_IHsmPhasePriv, (void**) &pPhasePriv)); WsbAffirmHr(pPhasePriv->SetPhase(phase)); hr = pEnum->Find(pPhasePriv, IID_IHsmPhasePriv, (void**) &pFoundPhasePriv); // If one wasn't found then add it, otherwise, just update the state. if (hr == WSB_E_NOTFOUND) { hr = S_OK; WsbAffirmHr(pPhasePriv->AddItem(pScanItem, hrItem)); WsbAffirmHr(m_pPhases->Add(pPhasePriv)); pFoundPhasePriv = pPhasePriv; } else if (SUCCEEDED(hr)) { WsbAffirmHr(pFoundPhasePriv->AddItem(pScanItem, hrItem)); } pEnum = 0; // Update the session totals. WsbAffirmHr(EnumTotals(&pEnum)); WsbAffirmHr(CoCreateInstance(CLSID_CHsmSessionTotals, 0, CLSCTX_ALL, IID_IHsmSessionTotalsPriv, (void**) &pTotalsPriv)); WsbAffirmHr(pTotalsPriv->SetAction(action)); hr = pEnum->Find(pTotalsPriv, IID_IHsmSessionTotalsPriv, (void**) &pFoundTotalsPriv); // If one wasn't found then add it, otherwise, just update the state. if (hr == WSB_E_NOTFOUND) { hr = S_OK; WsbAffirmHr(pTotalsPriv->AddItem(pScanItem, hrItem)); WsbAffirmHr(m_pTotals->Add(pTotalsPriv)); pFoundTotalsPriv = pTotalsPriv; } else if (SUCCEEDED(hr)) { WsbAffirmHr(pFoundTotalsPriv->AddItem(pScanItem, hrItem)); } // If we had a error (other than just some information ones from the scanner), then // log it. if (((m_logControl & HSM_JOB_LOG_ITEMALL) != 0) || (((m_logControl & HSM_JOB_LOG_ITEMALLFAIL) != 0) && FAILED(hrItem)) || (((m_logControl & HSM_JOB_LOG_ITEMMOSTFAIL) != 0) && (FAILED(hrItem) && (hrItem != JOB_E_FILEEXCLUDED) && (hrItem != JOB_E_DOESNTMATCH)))) { WsbAffirmHr(pFoundPhasePriv->GetName(&phaseName, 0)); WsbAffirmHr(m_pResource->GetLogicalName(&resourceName, 0)); WsbAffirmHr(pScanItem->GetPathAndName(0, &itemPath, 0)); WsbLogEvent(JOB_MESSAGE_SESSION_ITEM_SKIPPED, 0, NULL, (OLECHAR*) m_name, (OLECHAR*) phaseName, (OLECHAR*) resourceName, WsbAbbreviatePath(itemPath, 120), WsbHrAsString(hrItem), NULL); } // Tell everyone about the item. // // NOTE: We might want to clone the phase and session totals so that the don't get // updated before the called method gets a chance to look at them. try { WsbAffirmHr(pFoundPhasePriv->QueryInterface(IID_IHsmPhase, (void**) &pFoundPhase)); WsbAffirmHr(pFoundTotalsPriv->QueryInterface(IID_IHsmSessionTotals, (void**) &pFoundTotals)); WsbAffirmHr(AdviseOfItem(pFoundPhase, pScanItem, hrItem, pFoundTotals)); } WsbCatchAndDo(hr2, ((IHsmSession*) this)->ProcessHr(phase, __FILE__, __LINE__, hr2);); } WsbCatch(hr); return(hr); } HRESULT CHsmSession::ProcessMediaState( IN HSM_JOB_PHASE phase, IN HSM_JOB_MEDIA_STATE state, IN OLECHAR* mediaName, IN HSM_JOB_MEDIA_TYPE mediaType, IN ULONG time ) /*++ Implements: IHsmSession::ProcessMediaState(). --*/ { HRESULT hr = S_OK; HRESULT hr2 = S_OK; CComPtr pEnum; CComPtr pPhasePriv; CComPtr pFoundPhasePriv; CComPtr pFoundPhase; try { // Record the state change in the phase object. WsbAffirmHr(EnumPhases(&pEnum)); WsbAffirmHr(CoCreateInstance(CLSID_CHsmPhase, 0, CLSCTX_ALL, IID_IHsmPhasePriv, (void**) &pPhasePriv)); WsbAffirmHr(pPhasePriv->SetPhase(phase)); hr = pEnum->Find(pPhasePriv, IID_IHsmPhasePriv, (void**) &pFoundPhasePriv); // If one wasn't found then add it, otherwise, just update the state. if (hr == WSB_E_NOTFOUND) { hr = S_OK; WsbAffirmHr(pPhasePriv->SetMediaState(state)); WsbAffirmHr(m_pPhases->Add(pPhasePriv)); pFoundPhasePriv = pPhasePriv; } else { WsbAffirmHr(pFoundPhasePriv->SetMediaState(state)); } // Tell everyone about the new state, but don't return an error if this fails. try { WsbAffirmHr(pFoundPhasePriv->QueryInterface(IID_IHsmPhase, (void**) &pFoundPhase)); WsbAffirmHr(AdviseOfMediaState(pFoundPhase, state, mediaName, mediaType, time)); } WsbCatchAndDo(hr2, ((IHsmSession*) this)->ProcessHr(phase, __FILE__, __LINE__, hr2);); } WsbCatch(hr); return(hr); } HRESULT CHsmSession::ProcessPriority( IN HSM_JOB_PHASE phase, IN HSM_JOB_PRIORITY priority ) /*++ Implements: IHsmSession::ProcessPriority(). --*/ { HRESULT hr = S_OK; HRESULT hr2 = S_OK; CComPtr pEnum; CComPtr pPhasePriv; CComPtr pFoundPhasePriv; CComPtr pFoundPhase; try { // Record the state change in the phase object. WsbAffirmHr(EnumPhases(&pEnum)); WsbAffirmHr(CoCreateInstance(CLSID_CHsmPhase, 0, CLSCTX_ALL, IID_IHsmPhasePriv, (void**) &pPhasePriv)); WsbAffirmHr(pPhasePriv->SetPhase(phase)); hr = pEnum->Find(pPhasePriv, IID_IHsmPhasePriv, (void**) &pFoundPhasePriv); // If one wasn't found then add it, otherwise, just update the state. if (hr == WSB_E_NOTFOUND) { hr = S_OK; WsbAffirmHr(pPhasePriv->SetPriority(priority)); WsbAffirmHr(m_pPhases->Add(pPhasePriv)); pFoundPhasePriv = pPhasePriv; } else { WsbAffirmHr(pFoundPhasePriv->SetPriority(priority)); } // Tell everyone about the new state, but don't return an error if this fails. try { WsbAffirmHr(pFoundPhasePriv->QueryInterface(IID_IHsmPhase, (void**) &pFoundPhase)); WsbAffirmHr(AdviseOfPriority(pFoundPhase)); } WsbCatchAndDo(hr2, ((IHsmSession*) this)->ProcessHr(phase, __FILE__, __LINE__, hr2);); } WsbCatch(hr); return(hr); } HRESULT CHsmSession::ProcessState( IN HSM_JOB_PHASE phase, IN HSM_JOB_STATE state, IN OLECHAR* currentPath, IN BOOL bLog ) /*++ Implements: IHsmSession::ProcessState(). --*/ { HRESULT hr = S_OK; HRESULT hr2 = S_OK; CComPtr pEnum; CComPtr pPhase; CComPtr pPhasePriv; CComPtr pFoundPhase; CComPtr pFoundPhasePriv; CComPtr pClonedPhase; CComPtr pClonedPhasePriv; HSM_JOB_STATE oldState; HSM_JOB_STATE otherState; HSM_JOB_STATE setState; BOOL shouldSet; LONGLONG items; LONGLONG skippedItems; LONGLONG errorItems; LONGLONG size; LONGLONG skippedSize; LONGLONG errorSize; ULONG days; USHORT hours; USHORT minutes; USHORT seconds; LONGLONG elapsedTime; OLECHAR itemsString[40]; OLECHAR sizeString[40]; OLECHAR skippedItemsString[40]; OLECHAR skippedSizeString[40]; OLECHAR errorItemsString[40]; OLECHAR errorSizeString[40]; OLECHAR durationString[40]; OLECHAR itemRateString[40]; OLECHAR byteRateString[40]; CWsbStringPtr resourceName; CWsbStringPtr phaseName; WsbTraceIn(OLESTR("CHsmSession::ProcessState"), OLESTR("Phase = <%d>, State = <%d>, Path = <%ls>, pLog = <%s>"), phase, state, WsbAbbreviatePath(currentPath, (WSB_TRACE_BUFF_SIZE - 100)), WsbBoolAsString(bLog)); try { // Record the state change in the phase object. WsbAffirmHr(EnumPhases(&pEnum)); WsbAffirmHr(CoCreateInstance(CLSID_CHsmPhase, 0, CLSCTX_ALL, IID_IHsmPhasePriv, (void**) &pPhasePriv)); WsbAffirmHr(pPhasePriv->SetPhase(phase)); hr = pEnum->Find(pPhasePriv, IID_IHsmPhasePriv, (void**) &pFoundPhasePriv); // If one wasn't found then add it, otherwise, just update the state. if (hr == WSB_E_NOTFOUND) { hr = S_OK; WsbAffirmHr(pPhasePriv->SetState(state)); WsbAffirmHr(m_pPhases->Add(pPhasePriv)); pFoundPhasePriv = pPhasePriv; } else { WsbAffirmHr(pFoundPhasePriv->SetState(state)); } // Put something in the event log that indicates when is happening with the session. if (((m_logControl & HSM_JOB_LOG_STATE) != 0) && (bLog)) { WsbAffirmHr(m_pResource->GetLogicalName(&resourceName, 0)); WsbAffirmHr(pFoundPhasePriv->GetName(&phaseName, 0)); WsbAffirmHr(pFoundPhasePriv->GetStats(&items, &size, &skippedItems, &skippedSize, &errorItems, &errorSize)); WsbAffirmHr(pFoundPhasePriv->GetElapsedTime(&days, &hours, &minutes, &seconds)); elapsedTime = max(1, ((LONGLONG) seconds) + 60 * (((LONGLONG) minutes) + 60 * (((LONGLONG) hours) + (24 * ((LONGLONG) days))))); swprintf(itemsString, OLESTR("%I64u"), items); swprintf(sizeString, OLESTR("%I64u"), size); swprintf(skippedItemsString, OLESTR("%I64u"), skippedItems); swprintf(skippedSizeString, OLESTR("%I64u"), skippedSize); swprintf(errorItemsString, OLESTR("%I64u"), errorItems); swprintf(errorSizeString, OLESTR("%I64u"), errorSize); swprintf(durationString, OLESTR("%2.2u:%2.2u:%2.2u"), hours + (24 * days), minutes, seconds); swprintf(itemRateString, OLESTR("%I64u"), items / elapsedTime); swprintf(byteRateString, OLESTR("%I64u"), size / elapsedTime); switch (state) { case HSM_JOB_STATE_STARTING: WsbLogEvent(JOB_MESSAGE_SESSION_STARTING, 0, NULL, (OLECHAR*) m_name, (OLECHAR*) phaseName, (OLECHAR*) resourceName, NULL); break; case HSM_JOB_STATE_RESUMING: WsbLogEvent(JOB_MESSAGE_SESSION_RESUMING, 0, NULL, (OLECHAR*) m_name, (OLECHAR*) phaseName, (OLECHAR*) resourceName, NULL); break; // If one hits this state, then change the overall state to this value case HSM_JOB_STATE_ACTIVE: WsbLogEvent(JOB_MESSAGE_SESSION_ACTIVE, 0, NULL, (OLECHAR*) m_name, (OLECHAR*) phaseName, (OLECHAR*) resourceName, NULL); break; case HSM_JOB_STATE_CANCELLING: WsbLogEvent(JOB_MESSAGE_SESSION_CANCELLING, 0, NULL, (OLECHAR*) m_name, (OLECHAR*) phaseName, (OLECHAR*) resourceName, NULL); break; case HSM_JOB_STATE_PAUSING: WsbLogEvent(JOB_MESSAGE_SESSION_PAUSING, 0, NULL, (OLECHAR*) m_name, (OLECHAR*) phaseName, (OLECHAR*) resourceName, NULL); break; case HSM_JOB_STATE_SUSPENDING: WsbLogEvent(JOB_MESSAGE_SESSION_SUSPENDING, 0, NULL, (OLECHAR*) m_name, (OLECHAR*) phaseName, (OLECHAR*) resourceName, NULL); break; case HSM_JOB_STATE_CANCELLED: WsbLogEvent(JOB_MESSAGE_SESSION_CANCELLED, 0, NULL, (OLECHAR*) m_name, (OLECHAR*) phaseName, (OLECHAR*) resourceName, itemsString, sizeString, skippedItemsString, skippedSizeString, errorItemsString, errorSizeString, durationString, itemRateString, byteRateString, NULL); break; case HSM_JOB_STATE_DONE: WsbLogEvent(JOB_MESSAGE_SESSION_DONE, 0, NULL, (OLECHAR*) m_name, (OLECHAR*) phaseName, (OLECHAR*) resourceName, itemsString, sizeString, skippedItemsString, skippedSizeString, errorItemsString, errorSizeString, durationString, itemRateString, byteRateString, NULL); break; case HSM_JOB_STATE_FAILED: WsbLogEvent(JOB_MESSAGE_SESSION_FAILED, 0, NULL, (OLECHAR*) m_name, (OLECHAR*) phaseName, (OLECHAR*) resourceName, itemsString, sizeString, skippedItemsString, skippedSizeString, errorItemsString, errorSizeString, durationString, itemRateString, byteRateString, NULL); break; case HSM_JOB_STATE_IDLE: WsbLogEvent(JOB_MESSAGE_SESSION_IDLE, 0, NULL, (OLECHAR*) m_name, (OLECHAR*) phaseName, (OLECHAR*) resourceName, NULL); break; case HSM_JOB_STATE_PAUSED: WsbLogEvent(JOB_MESSAGE_SESSION_PAUSED, 0, NULL, (OLECHAR*) m_name, (OLECHAR*) phaseName, (OLECHAR*) resourceName, itemsString, sizeString, skippedItemsString, skippedSizeString, errorItemsString, errorSizeString, durationString, itemRateString, byteRateString, NULL); break; case HSM_JOB_STATE_SUSPENDED: WsbLogEvent(JOB_MESSAGE_SESSION_SUSPENDED, 0, NULL, (OLECHAR*) m_name, (OLECHAR*) phaseName, (OLECHAR*) resourceName, itemsString, sizeString, skippedItemsString, skippedSizeString, errorItemsString, errorSizeString, durationString, itemRateString, byteRateString, NULL); break; case HSM_JOB_STATE_SKIPPED: WsbLogEvent(JOB_MESSAGE_SESSION_SKIPPED, 0, NULL, (OLECHAR*) m_name, (OLECHAR*) phaseName, (OLECHAR*) resourceName, NULL); break; default: break; } } // Tell everyone about the new state, but don't return an error if this fails. try { WsbAffirmHr(pFoundPhasePriv->QueryInterface(IID_IHsmPhase, (void**) &pFoundPhase)); WsbAffirmHr(AdviseOfState(pFoundPhase, currentPath)); } WsbCatchAndDo(hr2, ((IHsmSession*) this)->ProcessHr(phase, __FILE__, __LINE__, hr2);); // We may need to generate the "HSM_JOB_PHASE_ALL" messages. This is the session // summary for all the phases. // Remember the state, and only send a message if the state changes. We also need some strings to // log messages. oldState = m_state; switch (state) { // If one hits this state, then change the overall state to this value. // Also increment the activePhases count. case HSM_JOB_STATE_STARTING: if (0 == m_activePhases) { m_state = state; } m_activePhases++; break; case HSM_JOB_STATE_RESUMING: if (0 == m_activePhases) { m_state = state; } m_activePhases++; break; // If one hits this state, then change the overall state to this value case HSM_JOB_STATE_ACTIVE: if ((HSM_JOB_STATE_STARTING == m_state) || (HSM_JOB_STATE_RESUMING == m_state)) { m_state = state; } break; // If all change to this state, then change to this value. case HSM_JOB_STATE_CANCELLING: case HSM_JOB_STATE_PAUSING: case HSM_JOB_STATE_SUSPENDING: shouldSet = TRUE; for (hr2 = pEnum->First(IID_IHsmPhase, (void**) &pPhase); SUCCEEDED(hr2) && shouldSet; hr2 = pEnum->Next(IID_IHsmPhase, (void**) &pPhase)) { WsbAffirmHr(pPhase->GetState(&otherState)); if ((state != otherState) && (HSM_JOB_STATE_SKIPPED != otherState)) { shouldSet = FALSE; } pPhase = 0; } if (state == HSM_JOB_STATE_CANCELLING) { // Some jobs might need to know that a phase is canceling m_isCanceling = TRUE; } if (shouldSet) { m_state = state; } break; // Decrement the the activePhases count. If all phases are in one of these states // (i.e. activeSessions count goes to 0), then change it to the "worst" state (first // in the follwing list) : // 1) Cancelled // 2) Failed // 3) Suspended // 4) Paused // 5) Idle // 6) Done case HSM_JOB_STATE_CANCELLED: case HSM_JOB_STATE_DONE: case HSM_JOB_STATE_FAILED: case HSM_JOB_STATE_IDLE: case HSM_JOB_STATE_PAUSED: case HSM_JOB_STATE_SUSPENDED: if (m_activePhases > 0) { m_activePhases--; if (m_activePhases == 0) { shouldSet = FALSE; setState = state; for (hr2 = pEnum->First(IID_IHsmPhase, (void**) &pPhase); SUCCEEDED(hr2); hr2 = pEnum->Next(IID_IHsmPhase, (void**) &pPhase)) { WsbAffirmHr(pPhase->GetState(&otherState)); switch (otherState) { case HSM_JOB_STATE_CANCELLED: shouldSet = TRUE; setState = otherState; break; case HSM_JOB_STATE_FAILED: if (HSM_JOB_STATE_CANCELLED != setState) { shouldSet = TRUE; setState = otherState; } break; case HSM_JOB_STATE_SUSPENDED: if ((HSM_JOB_STATE_CANCELLED != setState) && (HSM_JOB_STATE_FAILED != setState)) { shouldSet = TRUE; setState = otherState; } break; case HSM_JOB_STATE_IDLE: if ((HSM_JOB_STATE_CANCELLED != setState) && (HSM_JOB_STATE_FAILED != setState) && (HSM_JOB_STATE_SUSPENDED != setState)) { shouldSet = TRUE; setState = otherState; } break; case HSM_JOB_STATE_PAUSED: if (HSM_JOB_STATE_DONE == setState) { shouldSet = TRUE; setState = otherState; } break; case HSM_JOB_STATE_DONE: if (HSM_JOB_STATE_DONE == setState) { shouldSet = TRUE; } break; case HSM_JOB_STATE_ACTIVE: case HSM_JOB_STATE_CANCELLING: case HSM_JOB_STATE_PAUSING: case HSM_JOB_STATE_RESUMING: case HSM_JOB_STATE_SKIPPED: case HSM_JOB_STATE_STARTING: case HSM_JOB_STATE_SUSPENDING: default: break; } pPhase = 0; } if (shouldSet) { m_state = setState; } } } break; case HSM_JOB_STATE_SKIPPED: break; default: break; } if (oldState != m_state) { try { WsbAffirmHr(pFoundPhasePriv->Clone(&pClonedPhasePriv)); WsbAffirmHr(pClonedPhasePriv->SetPhase(HSM_JOB_PHASE_ALL)); WsbAffirmHr(pClonedPhasePriv->QueryInterface(IID_IHsmPhase, (void**) &pClonedPhase)); WsbAffirmHr(AdviseOfState(pClonedPhase, currentPath)); } WsbCatchAndDo(hr2, ((IHsmSession*) this)->ProcessHr(phase, __FILE__, __LINE__, hr2);); } } WsbCatch(hr); WsbTraceOut(OLESTR("CHsmSession::ProcessState"), OLESTR("hr = <%ls>, State = <%d>, ActivePhases = <%lu>"), WsbHrAsString(hr), m_state, m_activePhases); return(hr); } HRESULT CHsmSession::ProcessString( IN HSM_JOB_PHASE /*phase*/, IN OLECHAR* string ) /*++ Implements: IHsmSession::ProcessString(). --*/ { HRESULT hr = S_OK; try { // Don't know what to really do with it, but for now just print it. _putts(string); } WsbCatch(hr); return(hr); } HRESULT CHsmSession::Resume( IN HSM_JOB_PHASE phase ) /*++ Implements: IHsmSession::Resume(). --*/ { return(AdviseOfEvent(phase, HSM_JOB_EVENT_RESUME)); } HRESULT CHsmSession::Save( IN IStream* pStream, IN BOOL clearDirty ) /*++ Implements: IPersistStream::Save(). --*/ { HRESULT hr = S_OK; CComPtr pPersistStream; WsbTraceIn(OLESTR("CHsmSession::Save"), OLESTR("clearDirty = <%ls>"), WsbBoolAsString(clearDirty)); try { WsbAssert(0 != pStream, E_POINTER); hr = E_NOTIMPL; } WsbCatch(hr); WsbTraceOut(OLESTR("CHsmSession::Save"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return(hr); } HRESULT CHsmSession::SetAdviseInterval( IN LONGLONG interval ) /*++ Implements: IHsmSession::SetAdviseInterval --*/ { m_adviseInterval = interval; m_isDirty = TRUE; return(S_OK); } HRESULT CHsmSession::Start( IN OLECHAR* name, IN ULONG logControl, IN GUID hsmId, IN IHsmJob* pJob, IN IFsaResource* pResource, IN ULONG runId, IN ULONG subRunId ) /*++ Implements: IHsmSession::Start(). --*/ { HRESULT hr = S_OK; try { WsbAssert(0 != pResource, E_POINTER); // You can only use a session once (i.e. no restart). WsbAssert(m_pResource == 0, E_UNEXPECTED); // Store the information that has been provided. m_logControl = logControl; m_name = name; m_hsmId = hsmId; m_runId = runId; m_subRunId = subRunId; m_pJob = pJob; m_pResource = pResource; m_isDirty = TRUE; } WsbCatch(hr); return(hr); } HRESULT CHsmSession::Suspend( IN HSM_JOB_PHASE phase ) /*++ Implements: IHsmSession::Suspend(). --*/ { return(AdviseOfEvent(phase, HSM_JOB_EVENT_SUSPEND)); } HRESULT CHsmSession::Test( OUT USHORT* passed, OUT USHORT* failed ) /*++ Implements: IWsbTestable::Test(). --*/ { HRESULT hr = S_OK; try { WsbAssert(0 != passed, E_POINTER); WsbAssert(0 != failed, E_POINTER); *passed = 0; *failed = 0; } WsbCatch(hr); return(hr); } HRESULT CHsmSession::IsCanceling( void ) /*++ Implements: IHsmSession::IsCanceling(). --*/ { HRESULT hr = S_FALSE; if (m_isCanceling) { hr = S_OK; } return(hr); }