windows-nt/Source/XPSP1/NT/base/fs/hsm/job/hsmacrsc.cpp

795 lines
20 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
<EFBFBD> 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<IFsaResource> 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<IFsaResource> 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<IFsaResource> pResource;
CComPtr<IFsaResourcePriv> pResourcePriv;
CComPtr<IHsmServer> 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<IWsbIndexedCollection> pCollection;
WsbAffirmHr(pHsm->GetManagedResources(&pCollection));
CComPtr<IWsbCreateLocalObject> pCreate;
WsbAffirmHr(pHsm->QueryInterface(IID_IWsbCreateLocalObject, (void**) &pCreate));
CComPtr<IHsmManagedResource> 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<IFsaResource> pResource;
CComPtr<IHsmServer> pHsm;
CComPtr<IWsbCreateLocalObject> pCreateObj;
CComPtr<IHsmActionOnResourcePreScan> 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<IFsaUnmanageDb> pUnmanageDb;
CComPtr<IWsbDbSession> pDbSession;
CComPtr<IFsaUnmanageRec> pUnmanageRec;
BOOL bDbOpen = FALSE;
WsbTraceIn(OLESTR("CHsmActionOnResourcePreScanUnmanage::Do"), OLESTR(""));
try {
CComPtr<IFsaResourcePriv> pResourcePriv;
CComPtr<IFsaScanItem> pScanItem;
CComPtr<IHsmServer> 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);
}