/*++ © 1998 Seagate Software, Inc. All rights reserved. Module Name: hsmacrsc.cpp Abstract: This component represents the actions that can be performed by a job on a resource either before or after the scan. Author: Ronald G. White [ronw] 14-Aug-1997 Revision History: --*/ #include "stdafx.h" #include "stdio.h" #include "wsb.h" #include "job.h" #include "HsmConn.h" #include "hsmacrsc.h" #include "fsaprv.h" #include "fsa.h" #define WSB_TRACE_IS WSB_TRACE_BIT_JOB HRESULT CHsmActionOnResource::GetName( OUT OLECHAR** pName, IN ULONG bufferSize ) /*++ Implements: IHsmActionOnResource::GetName(). --*/ { HRESULT hr = S_OK; CWsbStringPtr tmpString; try { WsbAssert(0 != pName, E_POINTER); WsbAffirmHr(tmpString.LoadFromRsc(_Module.m_hInst, m_nameId)); WsbAffirmHr(tmpString.CopyTo(pName, bufferSize)); } WsbCatch(hr); return(hr); } HRESULT CHsmActionOnResource::Load( IN IStream* pStream ) /*++ Implements: IPersistStream::Load(). --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CHsmActionOnResource::Load"), OLESTR("")); try { WsbAssert(0 != pStream, E_POINTER); WsbAffirmHr(WsbLoadFromStream(pStream, &m_nameId)); } WsbCatch(hr); WsbTraceOut(OLESTR("CHsmActionOnResource::Load"), OLESTR("hr = <%ls>, nameId = <%lu>"), WsbHrAsString(hr), m_nameId); return(hr); } HRESULT CHsmActionOnResource::Save( IN IStream* pStream, IN BOOL clearDirty ) /*++ Implements: IPersistStream::Save(). --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CHsmActionOnResource::Save"), OLESTR("clearDirty = <%ls>"), WsbBoolAsString(clearDirty)); try { WsbAssert(0 != pStream, E_POINTER); WsbAffirmHr(WsbSaveToStream(pStream, m_nameId)); // If we got it saved and we were asked to clear the dirty bit, then // do so now. if (clearDirty) { m_isDirty = FALSE; } } WsbCatch(hr); WsbTraceOut(OLESTR("CHsmActionOnResource::Save"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return(hr); } HRESULT CHsmActionOnResourcePostValidate::Do( IHsmJobWorkItem* pWorkItem, HSM_JOB_STATE state ) /*++ Implements: IHsmActionOnResource::Do(). --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CHsmActionOnResourcePostValidate::Do"), OLESTR("pWorkItem = %p, state = %ld"), pWorkItem, (LONG)state); try { GUID id; CComPtr pResource; WsbAssertPointer(pWorkItem); // Get resource associated with this work item WsbAffirmHr(pWorkItem->GetResourceId(&id)); WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_RESOURCE, id, IID_IFsaResource, (void**) &pResource)); // Tell the resource what's happening WsbAffirmHr(pResource->EndValidate(state)); } WsbCatch(hr); WsbTraceOut(OLESTR("CHsmActionOnResourcePostValidate::Do"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return(hr); } HRESULT CHsmActionOnResourcePostValidate::GetClassID( OUT CLSID* pClsid ) /*++ Implements: IPersist::GetClassID(). --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CHsmActionOnResourcePostValidate::GetClassID"), OLESTR("")); try { WsbAssert(0 != pClsid, E_POINTER); *pClsid = CLSID_CHsmActionOnResourcePostValidate; } WsbCatch(hr); WsbTraceOut(OLESTR("CHsmActionOnResourcePostValidate::GetClassID"), OLESTR("hr = <%ls>, CLSID = <%ls>"), WsbHrAsString(hr), WsbGuidAsString(*pClsid)); return(hr); } HRESULT CHsmActionOnResourcePostValidate::FinalConstruct( void ) /*++ Implements: CComObjectRoot::FinalConstruct(). --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CHsmActionOnResourcePostValidate::FinalConstruct"), OLESTR("")); try { WsbAffirmHr(CHsmActionOnResource::FinalConstruct()); m_nameId = IDS_HSMACTIONONRESOURCEPOSTVALIDATE_ID; } WsbCatch(hr); WsbTraceOut(OLESTR("CHsmActionOnResourcePostValidate::FinalConstruct"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return(hr); } HRESULT CHsmActionOnResourcePreValidate::Do( IHsmJobWorkItem* pWorkItem, IHsmJobDef* pJobDef ) /*++ Implements: IHsmActionOnResource::Do(). --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CHsmActionOnResourcePreValidate::Do"), OLESTR("pWorkItem = %p, pJobDef=%p"), pWorkItem, pJobDef); try { GUID id; CComPtr pResource; WsbAssertPointer(pWorkItem); // Get resource associated with this work item WsbAffirmHr(pWorkItem->GetResourceId(&id)); WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_RESOURCE, id, IID_IFsaResource, (void**) &pResource)); // Tell the resource what's happening WsbAffirmHr(pResource->BeginValidate()); } WsbCatch(hr); WsbTraceOut(OLESTR("CHsmActionOnResourcePreValidate::Do"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return(hr); } HRESULT CHsmActionOnResourcePreValidate::GetClassID( OUT CLSID* pClsid ) /*++ Implements: IPersist::GetClassID(). --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CHsmActionOnResourcePreValidate::GetClassID"), OLESTR("")); try { WsbAssert(0 != pClsid, E_POINTER); *pClsid = CLSID_CHsmActionOnResourcePreValidate; } WsbCatch(hr); WsbTraceOut(OLESTR("CHsmActionOnResourcePreValidate::GetClassID"), OLESTR("hr = <%ls>, CLSID = <%ls>"), WsbHrAsString(hr), WsbGuidAsString(*pClsid)); return(hr); } HRESULT CHsmActionOnResourcePreValidate::FinalConstruct( void ) /*++ Implements: CComObjectRoot::FinalConstruct(). --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CHsmActionOnResourcePreValidate::FinalConstruct"), OLESTR("")); try { WsbAffirmHr(CHsmActionOnResource::FinalConstruct()); m_nameId = IDS_HSMACTIONONRESOURCEPREVALIDATE_ID; } WsbCatch(hr); WsbTraceOut(OLESTR("CHsmActionOnResourcePreValidate::FinalConstruct"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return(hr); } HRESULT CHsmActionOnResourcePostUnmanage::Do( IHsmJobWorkItem* pWorkItem, HSM_JOB_STATE state ) /*++ Implements: IHsmActionOnResource::Do(). --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CHsmActionOnResourcePostUnmanage::Do"), OLESTR("pWorkItem = %p, state = %ld"), pWorkItem, (LONG)state); try { GUID id, hsmId; CComPtr pResource; CComPtr pResourcePriv; CComPtr pHsm; WsbAssertPointer(pWorkItem); // Get resource associated with this work item WsbAffirmHr(pWorkItem->GetResourceId(&id)); WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_RESOURCE, id, IID_IFsaResource, (void**) &pResource)); // Delete the temporary Unmanage database that we use for scanning in the right order (ignore errors) hr = pResource->QueryInterface(IID_IFsaResourcePriv, (void**) &pResourcePriv); if (SUCCEEDED(hr)) { // ignore errors (void)pResourcePriv->TerminateUnmanageDb(); } // Get back to the HSM system so we can remove it WsbAffirmHr(pResource->GetManagingHsm(&hsmId)); WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, hsmId, IID_IHsmServer, (void**) &pHsm)); // Get the collection and find the coresponding object CComPtr pCollection; WsbAffirmHr(pHsm->GetManagedResources(&pCollection)); CComPtr pCreate; WsbAffirmHr(pHsm->QueryInterface(IID_IWsbCreateLocalObject, (void**) &pCreate)); CComPtr pHsmResourceKey, pHsmResource; WsbAffirmHr(pCreate->CreateInstance(CLSID_CHsmManagedResource, IID_IHsmManagedResource, (void**) &pHsmResourceKey)); WsbAffirmHr(pHsmResourceKey->SetResourceId(id)); WsbAffirmHr(pCollection->Find(pHsmResourceKey, IID_IHsmManagedResource, (void**) &pHsmResource)); // Remove the volume from management WsbAffirmHr(pCollection->RemoveAndRelease(pHsmResource)); } WsbCatch(hr); WsbTraceOut(OLESTR("CHsmActionOnResourcePostUnmanage::Do"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return(hr); } HRESULT CHsmActionOnResourcePostUnmanage::GetClassID( OUT CLSID* pClsid ) /*++ Implements: IPersist::GetClassID(). --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CHsmActionOnResourcePostUnmanage::GetClassID"), OLESTR("")); try { WsbAssert(0 != pClsid, E_POINTER); *pClsid = CLSID_CHsmActionOnResourcePostUnmanage; } WsbCatch(hr); WsbTraceOut(OLESTR("CHsmActionOnResourcePostUnmanage::GetClassID"), OLESTR("hr = <%ls>, CLSID = <%ls>"), WsbHrAsString(hr), WsbGuidAsString(*pClsid)); return(hr); } HRESULT CHsmActionOnResourcePostUnmanage::FinalConstruct( void ) /*++ Implements: CComObjectRoot::FinalConstruct(). --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CHsmActionOnResourcePostUnmanage::FinalConstruct"), OLESTR("")); try { WsbAffirmHr(CHsmActionOnResource::FinalConstruct()); m_nameId = IDS_HSMACTIONONRESOURCEPOSTUNMANAGE_ID; } WsbCatch(hr); WsbTraceOut(OLESTR("CHsmActionOnResourcePostUnmanage::FinalConstruct"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return(hr); } HRESULT CHsmActionOnResourcePreUnmanage::Do( IHsmJobWorkItem* pWorkItem, IHsmJobDef* pJobDef ) /*++ Implements: IHsmActionOnResource::Do(). --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CHsmActionOnResourcePreUnmanage::Do"), OLESTR("pWorkItem = %p, pJobDef=%p"), pWorkItem, pJobDef); try { GUID id; CComPtr pResource; CComPtr pHsm; CComPtr pCreateObj; CComPtr pActionResourcePreScan; GUID hsmId = GUID_NULL; WsbAssertPointer(pWorkItem); WsbAssertPointer(pJobDef); // Create a pre-scan action and assign to the job definition // Note: Naturally, creating the pre-scan action would have been done in CHsmJobDef::InitAs // However, since we cannot add new persistent members to JobDef (.col files mismatch on upgrade...), // we let the pre-action to create a pre-scan-action if necessary WsbAffirmHr(pJobDef->SetUseDbIndex(TRUE)); // hsm-id is not used today in HsmConnectFromId for HSMCONN_TYPE_HSM // When it does - use IFsaResource::GetManagingHsm to get the hsm-id WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, hsmId, IID_IHsmServer, (void**) &pHsm)); WsbAffirmHr(pHsm->QueryInterface(IID_IWsbCreateLocalObject, (void**) &pCreateObj)); WsbAffirmHr(pCreateObj->CreateInstance(CLSID_CHsmActionOnResourcePreScanUnmanage, IID_IHsmActionOnResourcePreScan, (void**) &pActionResourcePreScan)); WsbAffirmHr(pJobDef->SetPreScanActionOnResource(pActionResourcePreScan)); // Get resource associated with this work item WsbAffirmHr(pWorkItem->GetResourceId(&id)); WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_RESOURCE, id, IID_IFsaResource, (void**) &pResource)); // Tell the resource what's happening WsbAffirmHr(pResource->SetIsDeletePending( TRUE )); } WsbCatch(hr); WsbTraceOut(OLESTR("CHsmActionOnResourcePreUnmanage::Do"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return(hr); } HRESULT CHsmActionOnResourcePreUnmanage::GetClassID( OUT CLSID* pClsid ) /*++ Implements: IPersist::GetClassID(). --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CHsmActionOnResourcePreUnmanage::GetClassID"), OLESTR("")); try { WsbAssert(0 != pClsid, E_POINTER); *pClsid = CLSID_CHsmActionOnResourcePreUnmanage; } WsbCatch(hr); WsbTraceOut(OLESTR("CHsmActionOnResourcePreUnmanage::GetClassID"), OLESTR("hr = <%ls>, CLSID = <%ls>"), WsbHrAsString(hr), WsbGuidAsString(*pClsid)); return(hr); } HRESULT CHsmActionOnResourcePreUnmanage::FinalConstruct( void ) /*++ Implements: CComObjectRoot::FinalConstruct(). --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CHsmActionOnResourcePreUnmanage::FinalConstruct"), OLESTR("")); try { WsbAffirmHr(CHsmActionOnResource::FinalConstruct()); m_nameId = IDS_HSMACTIONONRESOURCEPREUNMANAGE_ID; } WsbCatch(hr); WsbTraceOut(OLESTR("CHsmActionOnResourcePreUnmanage::FinalConstruct"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return(hr); } HRESULT CHsmActionOnResourcePreScanUnmanage::Do( IFsaResource* pFsaResource, IHsmSession* pSession ) /*++ Implements: IHsmActionOnResource::Do(). --*/ { HRESULT hr = S_OK; CComPtr pUnmanageDb; CComPtr pDbSession; CComPtr pUnmanageRec; BOOL bDbOpen = FALSE; WsbTraceIn(OLESTR("CHsmActionOnResourcePreScanUnmanage::Do"), OLESTR("")); try { CComPtr pResourcePriv; CComPtr pScanItem; CComPtr pHsmServer; GUID hsmId = GUID_NULL; // Scan according to RP index and fill the Db // Don't need recursive scanning since we scan the RP index of the volume hr = pFsaResource->FindFirstInRPIndex(pSession, &pScanItem); if (SUCCEEDED(hr)) { // At least one managed file is found... // Initialize the Unmanaged Db for this resource WsbAffirmHr(pFsaResource->QueryInterface(IID_IFsaResourcePriv, (void**) &pResourcePriv)); WsbAffirmHr(pResourcePriv->InitializeUnmanageDb()); // Get and open the database WsbAffirmHr(pResourcePriv->GetUnmanageDb(IID_IFsaUnmanageDb, (void**) &pUnmanageDb)); WsbAffirmHr(pUnmanageDb->Open(&pDbSession)); bDbOpen = TRUE; // Get a record to work with WsbAffirmHr(pUnmanageDb->GetEntity(pDbSession, UNMANAGE_REC_TYPE, IID_IFsaUnmanageRec, (void**) &pUnmanageRec)); // Get HSM Server // Note: hsm-id is not used today in HsmConnectFromId for HSMCONN_TYPE_HSM // When it does - use IFsaResource::GetManagingHsm to get the hsm-id WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, hsmId, IID_IHsmServer, (void**) &pHsmServer)); } while (SUCCEEDED(hr)) { LONGLONG offset = 0; LONGLONG size = 0; FSA_PLACEHOLDER placeholder; GUID mediaId; LONGLONG fileOffset; LONGLONG fileId; LONGLONG segOffset; hr = pScanItem->GetPlaceholder(offset, size, &placeholder); if (S_OK == hr) { // File must be managed by HSM // If the file is truncated, then we need to add to the Db if (pScanItem->IsTruncated(offset, size) == S_OK) { // Get segment details from the Engine and calculate absolute offset WsbAffirmHr(pHsmServer->GetSegmentPosition(placeholder.bagId, placeholder.fileStart, placeholder.fileSize, &mediaId, &segOffset)); fileOffset = segOffset + placeholder.fileStart + placeholder.dataStart; // Add to the Unmanage database WsbAffirmHr(pScanItem->GetFileId(&fileId)); WsbAffirmHr(pUnmanageRec->SetMediaId(mediaId)); WsbAffirmHr(pUnmanageRec->SetFileOffset(fileOffset)); WsbAffirmHr(pUnmanageRec->SetFileId(fileId)); WsbAffirmHr(pUnmanageRec->MarkAsNew()); WsbAffirmHr(pUnmanageRec->Write()); } else { // Note: We will continue here even if we fail to cleanup non-truncated files, because // the auto-truncator is suspended (so no premigrated files will become truncated while // the job is running) and this piece of code will be tried again in CFsaScanItem::Unmanage try { // For disaster recovery, it would be better to delete the placeholder // and THEN remove this file from the premigration list. Unfortunately, // after deleting the placeholder, the RemovePremigrated call fails // because it needs to get some information from the placeholder (which // is gone). So we do it in this order. hr = pFsaResource->RemovePremigrated(pScanItem, offset, size); if (WSB_E_NOTFOUND == hr) { // It's no tragedy if this file wasn't in the list since we were // going to delete it anyway (although it shouldn't happen) so // let's continue anyway hr = S_OK; } WsbAffirmHr(hr); WsbAffirmHr(pScanItem->DeletePlaceholder(offset, size)); } WsbCatchAndDo(hr, WsbTraceAlways(OLESTR("...PreScanUnmanage::Do: failed to handle premigrated file, hr = <%ls>\n"), WsbHrAsString(hr)); hr = S_OK; ); } } // Get next file hr = pFsaResource->FindNextInRPIndex(pScanItem); } if (hr == WSB_E_NOTFOUND) { hr = S_OK; } } WsbCatch(hr); if (bDbOpen) { pUnmanageRec = 0; (void)pUnmanageDb->Close(pDbSession); } if (! SUCCEEDED(hr)) { // Log an error message CWsbStringPtr tmpString; hr = pFsaResource->GetPath(&tmpString, 0); if (hr != S_OK) { tmpString = OLESTR(""); } WsbLogEvent(JOB_MESSAGE_UNMANAGE_PRESCAN_FAILED, 0, NULL, (WCHAR *)tmpString, WsbHrAsString(hr), NULL); } WsbTraceOut(OLESTR("CHsmActionOnResourcePreScanUnmanage::Do"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return(hr); } HRESULT CHsmActionOnResourcePreScanUnmanage::GetClassID( OUT CLSID* pClsid ) /*++ Implements: IPersist::GetClassID(). --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CHsmActionOnResourcePreScanUnmanage::GetClassID"), OLESTR("")); try { WsbAssert(0 != pClsid, E_POINTER); *pClsid = CLSID_CHsmActionOnResourcePreScanUnmanage; } WsbCatch(hr); WsbTraceOut(OLESTR("CHsmActionOnResourcePreScanUnmanage::GetClassID"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return(hr); } HRESULT CHsmActionOnResourcePreScanUnmanage::FinalConstruct( void ) /*++ Implements: CComObjectRoot::FinalConstruct(). --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CHsmActionOnResourcePreScanUnmanage::FinalConstruct"), OLESTR("")); try { WsbAffirmHr(CHsmActionOnResource::FinalConstruct()); m_nameId = IDS_HSMACTIONONRESOURCEPRESCANUNMANAGE_ID; } WsbCatch(hr); WsbTraceOut(OLESTR("CHsmActionOnResourcePreScanUnmanage::FinalConstruct"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return(hr); }