You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1549 lines
47 KiB
1549 lines
47 KiB
/*++
|
|
|
|
© 1998 Seagate Software, Inc. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
SegDb.cpp
|
|
|
|
Abstract:
|
|
|
|
This component is an provides the collection that contains the HSM segment records.
|
|
|
|
Author:
|
|
|
|
Cat Brant [cbrant] 12-Nov-1996
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "metaint.h"
|
|
#include "metaLib.h"
|
|
#include "engine.h"
|
|
#include "segdb.h"
|
|
|
|
#undef WSB_TRACE_IS
|
|
#define WSB_TRACE_IS WSB_TRACE_BIT_SEG
|
|
|
|
// SEG_APPEND_OK returns TRUE if bag segment 2 can be appended to
|
|
// segment 1
|
|
#define SEG_APPEND_OK(b1, s1, l1, b2, s2, l2) \
|
|
(IsEqualGUID(b1, b2) && (s1 + l1 == s2))
|
|
|
|
// SEG_EXPAND_OK returns TRUE if bag segment 2 can be added to
|
|
// segment 1
|
|
#define SEG_EXPAND_OK(b1, s1, l1, b2, s2, l2) \
|
|
(IsEqualGUID(b1, b2) && (s1 + l1 <= s2))
|
|
|
|
// SEG_CONTAINS returns TRUE if bag segment 1 contains (the first
|
|
// part of) segment 2
|
|
#define SEG_CONTAINS(b1, s1, l1, b2, s2, l2) \
|
|
(IsEqualGUID(b1, b2) && (s1 <= s2) && ((s1 + l1) > s2))
|
|
|
|
|
|
HRESULT
|
|
CSegDb::BagHoleAdd
|
|
(
|
|
IN IWsbDbSession* pDbSession,
|
|
IN GUID BagId,
|
|
IN LONGLONG SegStartLoc,
|
|
IN LONGLONG SegLen
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
ISegDb::BagHoleAdd
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CSegDb::BagHoleAdd"),
|
|
OLESTR("GUID = <%ls>, SegStartLoc = <%I64u>, SegLen = <%I64u>"),
|
|
WsbGuidAsString(BagId), SegStartLoc,
|
|
SegLen);
|
|
|
|
try {
|
|
BOOL found = FALSE;
|
|
CComPtr<IBagHole> pBagHole;
|
|
GUID l_BagId = GUID_NULL;
|
|
LONGLONG l_SegStartLoc = 0;
|
|
LONGLONG l_SegLen = 0;
|
|
|
|
WsbAffirmHr(GetEntity(pDbSession, HSM_BAG_HOLE_REC_TYPE, IID_IBagHole,
|
|
(void **)&pBagHole));
|
|
WsbAffirmHr(pBagHole->SetBagHole(BagId, SegStartLoc, 0));
|
|
|
|
// Look for a segment to which to append this one
|
|
WsbTrace(OLESTR("Finding BagHole Record: <%ls>, <%I64u>, <%I64u>\n"),
|
|
WsbGuidAsString(BagId),
|
|
SegStartLoc,
|
|
SegLen);
|
|
hr = pBagHole->FindLTE();
|
|
if (WSB_E_NOTFOUND == hr) {
|
|
hr = S_OK;
|
|
} else {
|
|
WsbAffirmHr(pBagHole->GetBagHole(&l_BagId, &l_SegStartLoc, &l_SegLen));
|
|
if (SEG_APPEND_OK(l_BagId, l_SegStartLoc, l_SegLen,
|
|
BagId, SegStartLoc, SegLen)) {
|
|
found = TRUE;
|
|
}
|
|
}
|
|
|
|
if (found) {
|
|
// Append this segment to the existing record
|
|
l_SegLen += SegLen;
|
|
} else {
|
|
// Create a new record
|
|
l_SegStartLoc = SegStartLoc;
|
|
l_SegLen = SegLen;
|
|
WsbAffirmHr(pBagHole->MarkAsNew());
|
|
}
|
|
WsbAffirmHr(pBagHole->SetBagHole(BagId, l_SegStartLoc, l_SegLen));
|
|
|
|
WsbTrace(OLESTR("Writing BagHole Record: <%ls>, <%I64u>, <%I64u>\n"),
|
|
WsbGuidAsString(BagId),
|
|
l_SegStartLoc,
|
|
l_SegLen);
|
|
WsbAffirmHr(pBagHole->Write());
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CSegDb::BagHoleAdd"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CSegDb::BagHoleFind
|
|
(
|
|
IN IWsbDbSession* pDbSession,
|
|
IN GUID BagId,
|
|
IN LONGLONG SegStartLoc,
|
|
IN LONGLONG SegLen,
|
|
OUT IBagHole** ppIBagHole
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
ISegDb::BagHoleFind
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CSegDb::BagHoleFind"),
|
|
OLESTR("GUID = <%ls>, SegStartLoc = <%I64u>, SegLen = <%I64u>"),
|
|
WsbGuidAsString(BagId), SegStartLoc,
|
|
SegLen);
|
|
|
|
try {
|
|
CComPtr<IBagHole> pBagHole;
|
|
GUID l_BagId;
|
|
LONGLONG l_SegStartLoc;
|
|
LONGLONG l_SegLen;
|
|
|
|
WsbAffirm(ppIBagHole != NULL, E_POINTER);
|
|
WsbAffirmHr(GetEntity(pDbSession, HSM_BAG_HOLE_REC_TYPE, IID_IBagHole,
|
|
(void **)&pBagHole));
|
|
WsbAffirmHr(pBagHole->SetBagHole(BagId, SegStartLoc, 0));
|
|
|
|
// Look for a segment that contains this one
|
|
WsbTrace(OLESTR("Finding BagHole Record: <%ls>, <%I64u>, <%I64u>\n"),
|
|
WsbGuidAsString(BagId),
|
|
SegStartLoc,
|
|
SegLen);
|
|
WsbAffirmHr(pBagHole->FindLTE());
|
|
|
|
// We found a record, see if it's the right one
|
|
WsbAffirmHr(pBagHole->GetBagHole(&l_BagId, &l_SegStartLoc, &l_SegLen));
|
|
if (SEG_CONTAINS(l_BagId, l_SegStartLoc, l_SegLen,
|
|
BagId, SegStartLoc, SegLen)) {
|
|
*ppIBagHole = pBagHole;
|
|
pBagHole.p->AddRef();
|
|
} else {
|
|
hr = WSB_E_NOTFOUND;
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CSegDb::BagHoleFind"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CSegDb::BagHoleSubtract
|
|
(
|
|
IN IWsbDbSession* pDbSession,
|
|
IN GUID BagId,
|
|
IN LONGLONG SegStartLoc,
|
|
IN LONGLONG SegLen
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
ISegDb::BagHoleSubtract
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CSegDb::BagHoleSubtract"),
|
|
OLESTR("GUID = <%ls>, SegStartLoc = <%I64u>, SegLen = <%I64u>"),
|
|
WsbGuidAsString(BagId),
|
|
SegStartLoc,
|
|
SegLen);
|
|
|
|
try {
|
|
GUID l_BagId;
|
|
LONGLONG l_SegStartLoc;
|
|
LONGLONG l_SegLen;
|
|
CComPtr<IBagHole> pBagHole;
|
|
|
|
// Find the segment record
|
|
WsbAffirmHr(BagHoleFind(pDbSession, BagId, SegStartLoc, SegLen, &pBagHole));
|
|
|
|
// Get the current data
|
|
WsbAffirmHr(pBagHole->GetBagHole(&l_BagId, &l_SegStartLoc, &l_SegLen));
|
|
|
|
// Determine where the hole is
|
|
if (l_SegStartLoc == SegStartLoc && l_SegLen == SegLen) {
|
|
// Hole is the entire segment -- delete it
|
|
WsbAffirmHr(pBagHole->Remove());
|
|
|
|
} else if (l_SegStartLoc == SegStartLoc) {
|
|
// Hole is at the beginning of the segment. Just update the
|
|
// existing segment
|
|
l_SegStartLoc += SegLen;
|
|
WsbAffirmHr(pBagHole->SetBagHole(BagId, l_SegStartLoc, l_SegLen));
|
|
WsbAffirmHr(pBagHole->Write());
|
|
|
|
} else if ((l_SegStartLoc + l_SegLen) == (SegStartLoc + SegLen)) {
|
|
// Hole is at the end of the segment. Just update the
|
|
// existing segment
|
|
l_SegLen -= SegLen;
|
|
WsbAffirmHr(pBagHole->SetBagHole(BagId, l_SegStartLoc, l_SegLen));
|
|
WsbAffirmHr(pBagHole->Write());
|
|
|
|
} else {
|
|
// Hole is in the middle of the segment. Update the
|
|
// existing record to be the first part.
|
|
LONGLONG oldLen = l_SegLen;
|
|
LONGLONG offset = (SegStartLoc + SegLen) - l_SegStartLoc;
|
|
|
|
l_SegLen = SegStartLoc - l_SegStartLoc;
|
|
WsbAffirmHr(pBagHole->SetBagHole(BagId, l_SegStartLoc, l_SegLen));
|
|
WsbAffirmHr(pBagHole->Write());
|
|
|
|
// Create a new record for the second part.
|
|
l_SegLen -= offset;
|
|
l_SegStartLoc += offset;
|
|
WsbAffirmHr(BagHoleAdd(pDbSession, BagId, l_SegStartLoc, l_SegLen));
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CSegDb::BagHoleSubtract"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CSegDb::FinalConstruct(
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This method does some initialization of the object that is necessary
|
|
after construction.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
S_OK
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
m_value = 0;
|
|
try {
|
|
|
|
WsbAssertHr(CWsbDb::FinalConstruct());
|
|
m_version = 1;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CSegDb::FinalRelease(
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This method does some termination of the object that is necessary
|
|
before destruction.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
S_OK
|
|
Anything returned by CWsbCollection::FinalDestruct().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
CWsbDb::FinalRelease();
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT
|
|
CSegDb::Test
|
|
(
|
|
OUT USHORT * pTestsPassed,
|
|
OUT USHORT* pTestsFailed
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
See IWsbTestable::Test().
|
|
|
|
Arguments:
|
|
|
|
See IWsbTestable::Test().
|
|
|
|
Return Value:
|
|
|
|
See IWsbTestable::Test().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
#ifdef THIS_CODE_IS_WRONG
|
|
// This is mostly wrong now
|
|
ULONG entries;
|
|
GUID lastBagId;
|
|
LONGLONG lastStartLoc;
|
|
GUID startBagId;
|
|
LONGLONG startSegStartLoc;
|
|
LONGLONG startSegLen;
|
|
USHORT startSegType;
|
|
GUID startPrimLoc;
|
|
LONGLONG startSecLoc;
|
|
USHORT testsRun = 0;
|
|
CComPtr<IWsbCollection> pColl;
|
|
CComPtr<ISegRec> pSegRec1;
|
|
CComPtr<ISegRec> pSegRec2;
|
|
CComPtr<ISegRec> pSegRec3;
|
|
CComPtr<ISegRec> pSegRec4;
|
|
CComPtr<ISegRec> pSegRec5;
|
|
CComPtr<ISegRec> pSegRec6;
|
|
CComPtr<ISegRec> pSegRec7;
|
|
CComPtr<ISegRec> pSegRec8;
|
|
CComPtr<ISegRec> pSegRec9;
|
|
CComPtr<ISegRec> pSegRec10;
|
|
CComPtr<ISegRec> pSegRec11;
|
|
|
|
WsbTraceIn(OLESTR("CSegDb::Test"), OLESTR(""));
|
|
|
|
*pTestsPassed = *pTestsFailed = 0;
|
|
try {
|
|
// Clear out any entries that might be present.
|
|
hr = S_OK;
|
|
try {
|
|
WsbAssertHr(Erase());
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
// There shouldn't be any entries.
|
|
hr = S_OK;
|
|
try {
|
|
WsbAssertHr(GetSegments(&pColl));
|
|
WsbAssertHr(pColl->GetEntries(&entries));
|
|
WsbAssert(0 == entries, E_FAIL);
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
// It should be empty.
|
|
hr = S_OK;
|
|
try {
|
|
WsbAssert(pColl->IsEmpty() == S_OK, E_FAIL);
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
// We need some collectable items to exercise the collection.
|
|
WsbAssertHr(GetEntity(pDbSession, HSM_SEG_REC_TYPE, IID_ISegRec, (void**) &pSegRec1));
|
|
WsbAssertHr(pSegRec1->SetSegmentRecord(CLSID_CWsbBool, 0, 6, 0, CLSID_CSegRec,0 ));
|
|
|
|
|
|
// Add the item to the collection.
|
|
hr = S_OK;
|
|
try {
|
|
WsbAssertHr(pSegRec1->Write());
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
// There should be 1 entry.
|
|
hr = S_OK;
|
|
try {
|
|
WsbAssertHr(pColl->GetEntries(&entries));
|
|
WsbAssert(1 == entries, E_FAIL);
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
// It should not be empty.
|
|
hr = S_OK;
|
|
try {
|
|
WsbAssert(pColl->IsEmpty() == S_FALSE, E_FAIL);
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
// Does it think it has the item?
|
|
hr = S_OK;
|
|
try {
|
|
WsbAssertHr(GetEntity(pDbSession, HSM_SEG_REC_TYPE, IID_ISegRec, (void**) &pSegRec2));
|
|
WsbAssertHr(pSegRec2->SetSegmentRecord(CLSID_CWsbBool, 0, 6, 0, CLSID_CSegRec,0 ));
|
|
WsbAssertHr(pSegRec2->FindEQ());
|
|
WsbAssert(pSegRec1->CompareToISegmentRecord(pSegRec2, NULL) == S_OK, E_FAIL);
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
// Add some more items
|
|
WsbAssertHr(pSegRec2->SetSegmentRecord(CLSID_CWsbGuid, 0, 5, 0, CLSID_CSegRec,0 ));
|
|
|
|
WsbAssertHr(GetEntity(pDbSession, HSM_SEG_REC_TYPE, IID_ISegRec, (void**) &pSegRec3));
|
|
WsbAssertHr(pSegRec3->SetSegmentRecord(CLSID_CWsbGuid, 0, 5, 0, CLSID_CSegRec,0 ));
|
|
|
|
// Add the items to the collection.
|
|
hr = S_OK;
|
|
try {
|
|
WsbAssertHr(pSegRec2->Write());
|
|
WsbAssertHr(pSegRec3->Write());
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
// There should be 3 entries.
|
|
hr = S_OK;
|
|
try {
|
|
WsbAssertHr(pColl->GetEntries(&entries));
|
|
WsbAssert(3 == entries, E_FAIL);
|
|
WsbAssertHr(pColl->OccurencesOf(pSegRec3, &entries));
|
|
WsbAssert(2 == entries, E_FAIL);
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
// Remove one of the two identical items.
|
|
hr = S_OK;
|
|
try {
|
|
WsbAssertHr(pSegRec3->FindEQ());
|
|
WsbAssertHr(pSegRec3->Remove());
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
// There should be 2 entries.
|
|
hr = S_OK;
|
|
try {
|
|
WsbAssertHr(pColl->GetEntries(&entries));
|
|
WsbAssert(2 == entries, E_FAIL);
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
// How many copies does it have?
|
|
hr = S_OK;
|
|
try {
|
|
WsbAssertHr(pColl->OccurencesOf(pSegRec1, &entries));
|
|
WsbAssert(1 == entries, E_FAIL);
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
hr = S_OK;
|
|
try {
|
|
WsbAssertHr(pColl->OccurencesOf(pSegRec3, &entries));
|
|
WsbAssert(1 == entries, E_FAIL);
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
// Can we find an entry?
|
|
hr = S_OK;
|
|
try {
|
|
WsbAssertHr(pSegRec3->FindEQ());
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
// Does the collection still contain it?
|
|
hr = S_OK;
|
|
try {
|
|
WsbAssert(pColl->Contains(pSegRec1) == S_OK, E_FAIL);
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
// Remove the last of the record, and verify
|
|
// that it can't be found. Then puit it back.
|
|
hr = S_OK;
|
|
try {
|
|
WsbAssertHr(pSegRec1->FindEQ());
|
|
WsbAssertHr(pSegRec1->Remove());
|
|
WsbAssert(pColl->Contains(pSegRec1) == S_FALSE, E_FAIL);
|
|
WsbAssertHr(pSegRec1->MarkAsNew());
|
|
WsbAssertHr(pSegRec1->Write());
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
try {
|
|
WsbAssertHr(pColl->RemoveAllAndRelease());
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
// It should be empty.
|
|
hr = S_OK;
|
|
try {
|
|
WsbAssert(pColl->IsEmpty() == S_OK, E_FAIL);
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
hr = S_OK;
|
|
try {
|
|
WsbAssertHr(Erase());
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
|
|
try {
|
|
WsbAssertHr(pSegRec1->SetSegmentRecord(CLSID_CWsbBool, 0, 6, 0, CLSID_CSegRec,0 ));
|
|
WsbAssertHr(pSegRec2->SetSegmentRecord(CLSID_CWsbGuid, 0, 5, 0, CLSID_CSegRec,0 ));
|
|
WsbAssertHr(pSegRec3->SetSegmentRecord(CLSID_CWsbGuid, 5, 5, 0, CLSID_CSegRec,0 ));
|
|
|
|
WsbAssertHr(GetEntity(HSM_SEG_REC_TYPE, IID_ISegRec, (void**) &pSegRec4));
|
|
WsbAssertHr(pSegRec4->SetSegmentRecord(CLSID_CWsbGuid, 10, 5, 0, CLSID_CSegRec,0 ));
|
|
|
|
WsbAssertHr(GetEntity(HSM_SEG_REC_TYPE, IID_ISegRec, (void**) &pSegRec5));
|
|
WsbAssertHr(pSegRec5->SetSegmentRecord(CLSID_CWsbGuid, 15, 5, 0, CLSID_CSegRec,0 ));
|
|
|
|
WsbAssertHr(GetEntity(HSM_SEG_REC_TYPE, IID_ISegRec, (void**) &pSegRec6));
|
|
WsbAssertHr(pSegRec6->SetSegmentRecord(CLSID_CWsbGuid, 20, 5, 0, CLSID_CSegRec,0 ));
|
|
|
|
WsbAssertHr(GetEntity(HSM_SEG_REC_TYPE, IID_ISegRec, (void**) &pSegRec7));
|
|
WsbAssertHr(pSegRec7->SetSegmentRecord(CLSID_CWsbGuid, 25, 5, 0, CLSID_CSegRec,0 ));
|
|
|
|
WsbAssertHr(GetEntity(HSM_SEG_REC_TYPE, IID_ISegRec, (void**) &pSegRec8));
|
|
WsbAssertHr(pSegRec8->SetSegmentRecord(CLSID_CWsbGuid, 30, 5, 0, CLSID_CSegRec,0 ));
|
|
|
|
WsbAssertHr(GetEntity(HSM_SEG_REC_TYPE, IID_ISegRec, (void**) &pSegRec9));
|
|
WsbAssertHr(pSegRec9->SetSegmentRecord(CLSID_CWsbGuid, 35, 5, 0, CLSID_CSegRec,0 ));
|
|
|
|
WsbAssertHr(GetEntity(HSM_SEG_REC_TYPE, IID_ISegRec, (void**) &pSegRec10));
|
|
WsbAssertHr(pSegRec10->SetSegmentRecord(CLSID_CWsbGuid, 40, 5, 0, CLSID_CSegRec,0 ));
|
|
|
|
// Add them in random order
|
|
WsbAssertHr(pColl->Add(pSegRec5));
|
|
WsbAssertHr(pColl->Add(pSegRec4));
|
|
WsbAssertHr(pColl->Add(pSegRec1));
|
|
WsbAssertHr(pColl->Add(pSegRec6));
|
|
WsbAssertHr(pColl->Add(pSegRec7));
|
|
WsbAssertHr(pColl->Add(pSegRec8));
|
|
WsbAssertHr(pColl->Add(pSegRec1));
|
|
WsbAssertHr(pColl->Add(pSegRec2));
|
|
WsbAssertHr(pColl->Add(pSegRec3));
|
|
WsbAssertHr(pColl->Add(pSegRec9));
|
|
WsbAssertHr(pColl->Add(pSegRec3));
|
|
WsbAssertHr(pColl->Add(pSegRec4));
|
|
WsbAssertHr(pColl->Add(pSegRec10));
|
|
WsbAssertHr(pColl->Add(pSegRec5));
|
|
WsbAssertHr(pColl->Add(pSegRec8));
|
|
WsbAssertHr(pColl->Add(pSegRec1));
|
|
WsbAssertHr(pColl->Add(pSegRec5));
|
|
WsbAssertHr(pColl->Add(pSegRec6));
|
|
WsbAssertHr(pColl->Add(pSegRec7));
|
|
WsbAssertHr(pColl->Add(pSegRec1));
|
|
WsbAssertHr(pColl->Add(pSegRec7));
|
|
WsbAssertHr(pColl->Add(pSegRec2));
|
|
WsbAssertHr(pColl->Add(pSegRec7));
|
|
WsbAssertHr(pColl->Add(pSegRec8));
|
|
WsbAssertHr(pColl->Add(pSegRec2));
|
|
WsbAssertHr(pColl->Add(pSegRec8));
|
|
WsbAssertHr(pColl->Add(pSegRec3));
|
|
WsbAssertHr(pColl->Add(pSegRec6));
|
|
WsbAssertHr(pColl->Add(pSegRec3));
|
|
WsbAssertHr(pColl->Add(pSegRec9));
|
|
WsbAssertHr(pColl->Add(pSegRec4));
|
|
WsbAssertHr(pColl->Add(pSegRec6));
|
|
WsbAssertHr(pColl->Add(pSegRec9));
|
|
WsbAssertHr(pColl->Add(pSegRec9));
|
|
WsbAssertHr(pColl->Add(pSegRec10));
|
|
WsbAssertHr(pColl->Add(pSegRec4));
|
|
WsbAssertHr(pColl->Add(pSegRec10));
|
|
WsbAssertHr(pColl->Add(pSegRec5));
|
|
WsbAssertHr(pColl->Add(pSegRec10));
|
|
WsbAssertHr(pColl->Add(pSegRec2));
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
try {
|
|
// Check that they're sorted
|
|
WsbAssertHr(GetEntity(HSM_SEG_REC_TYPE, IID_ISegRec, (void**) &pSegRec11));
|
|
WsbAssertHr(pSegRec11->First());
|
|
WsbAssertHr(pSegRec11->GetSegmentRecord(&startBagId, &startSegStartLoc, &startSegLen, &startSegType, &startPrimLoc, &startSecLoc));
|
|
lastBagId = startBagId;
|
|
lastStartLoc = startSegStartLoc;
|
|
hr = S_OK;
|
|
for ( ; ; ) {
|
|
hr = pSegRec11->Next();
|
|
if (hr != S_OK) break;
|
|
WsbAssertHr(pSegRec11->GetSegmentRecord(&startBagId, &startSegStartLoc, &startSegLen, &startSegType, &startPrimLoc, &startSecLoc));
|
|
WsbAssert(!IsEqualGUID(lastBagId, startBagId) ||
|
|
lastStartLoc <= startSegStartLoc, E_FAIL);
|
|
lastBagId = startBagId;
|
|
lastStartLoc = startSegStartLoc;
|
|
}
|
|
WsbAssert(hr == WSB_E_NOTFOUND, E_FAIL);
|
|
hr = S_OK;
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
try {
|
|
// Check that the last one is what we expect
|
|
WsbAssertHr(pSegRec11->Last());
|
|
WsbAssertHr(pSegRec11->CompareToISegmentRecord(pSegRec10, NULL));
|
|
|
|
// Look for a specific record
|
|
WsbAssertHr(pSegRec5->FindEQ());
|
|
|
|
// Check for near misses
|
|
WsbAssertHr(pSegRec11->SetSegmentRecord(CLSID_CWsbGuid, 23, 5, 0, CLSID_CSegRec,0 ));
|
|
WsbAssertHr(pSegRec11->FindGT());
|
|
WsbAssertHr(pSegRec11->CompareToISegmentRecord(pSegRec7, NULL));
|
|
|
|
WsbAssertHr(pSegRec11->SetSegmentRecord(CLSID_CWsbGuid, 21, 5, 0, CLSID_CSegRec,0 ));
|
|
WsbAssertHr(pSegRec11->FindLTE());
|
|
WsbAssertHr(pSegRec11->CompareToISegmentRecord(pSegRec6, NULL));
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
// Clear the DB so we can shut it down
|
|
hr = S_OK;
|
|
try {
|
|
WsbAssertHr(Erase());
|
|
WsbAssertHr(Close());
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
(*pTestsPassed)++;
|
|
} else {
|
|
(*pTestsFailed)++;
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
#else
|
|
*pTestsPassed = *pTestsFailed = 0;
|
|
#endif
|
|
WsbTraceOut(OLESTR("CSegDb::Test"), OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CSegDb::Erase (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
See ISegDb::Erase
|
|
|
|
Arguments:
|
|
|
|
See ISegDb::Erase
|
|
|
|
Return Value:
|
|
|
|
See ISegDb::Erase
|
|
|
|
--*/
|
|
{
|
|
|
|
HRESULT hr = E_NOTIMPL;
|
|
|
|
WsbTraceIn(OLESTR("CSegDb::Erase"),OLESTR(""));
|
|
|
|
try {
|
|
// To be done?
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CSegDb::Erase"), OLESTR("hr = <%ls>"),WsbHrAsString(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CSegDb::GetClassID(
|
|
OUT CLSID* pClsid
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IPersist::GetClassID().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
WsbAssert(0 != pClsid, E_POINTER);
|
|
*pClsid = CLSID_CSegDb;
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CSegDb::Initialize(
|
|
IN OLECHAR* root,
|
|
IN IWsbDbSys* pDbSys,
|
|
IN OUT BOOL* pCreateFlag
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
ISegDb::Initialize().
|
|
|
|
--*/
|
|
{
|
|
BOOL CreateFlag = FALSE;
|
|
HRESULT hr = S_OK;
|
|
CWsbStringPtr path;
|
|
|
|
WsbTraceIn(OLESTR("CSegDb::Initialize"),
|
|
OLESTR("root = <%ls>, CreateFlag = <%ls>"),
|
|
WsbAbbreviatePath(root, 120), WsbPtrToBoolAsString(pCreateFlag));
|
|
|
|
if (pCreateFlag) {
|
|
CreateFlag = *pCreateFlag;
|
|
}
|
|
|
|
try {
|
|
path = root;
|
|
WsbAffirmHr(path.Append(OLESTR("\\SegDb")));
|
|
|
|
m_pWsbDbSys = pDbSys;
|
|
WsbAffirmPointer(m_pWsbDbSys);
|
|
|
|
hr = Locate(path);
|
|
|
|
if (hr == STG_E_FILENOTFOUND && CreateFlag){
|
|
ULONG memSize;
|
|
|
|
hr = S_OK;
|
|
m_nRecTypes = 5;
|
|
|
|
memSize = m_nRecTypes * sizeof(IDB_REC_INFO);
|
|
m_RecInfo = (IDB_REC_INFO*)WsbAlloc(memSize);
|
|
WsbAffirm(0 != m_RecInfo, E_FAIL);
|
|
ZeroMemory(m_RecInfo, memSize);
|
|
|
|
// Segment records
|
|
m_RecInfo[0].Type = HSM_SEG_REC_TYPE;
|
|
m_RecInfo[0].EntityClassId = CLSID_CSegRec;
|
|
m_RecInfo[0].Flags = 0;
|
|
m_RecInfo[0].MinSize = 2 * WSB_BYTE_SIZE_GUID +
|
|
3 * WSB_BYTE_SIZE_LONGLONG + WSB_BYTE_SIZE_USHORT;
|
|
m_RecInfo[0].MaxSize = m_RecInfo[0].MinSize;
|
|
m_RecInfo[0].nKeys = 1;
|
|
|
|
memSize = m_RecInfo[0].nKeys * sizeof(IDB_KEY_INFO);
|
|
m_RecInfo[0].Key = (IDB_KEY_INFO*)WsbAlloc(memSize);
|
|
WsbAffirm(0 != m_RecInfo[0].Key, E_FAIL);
|
|
ZeroMemory(m_RecInfo[0].Key, memSize);
|
|
|
|
m_RecInfo[0].Key[0].Type = SEG_KEY_TYPE;
|
|
m_RecInfo[0].Key[0].Size = WSB_BYTE_SIZE_GUID +
|
|
WSB_BYTE_SIZE_LONGLONG;
|
|
m_RecInfo[0].Key[0].Flags = IDB_KEY_FLAG_DUP_ALLOWED;
|
|
|
|
// Media information
|
|
m_RecInfo[1].Type = HSM_MEDIA_INFO_REC_TYPE;
|
|
m_RecInfo[1].EntityClassId = CLSID_CMediaInfo;
|
|
m_RecInfo[1].Flags = 0;
|
|
m_RecInfo[1].MinSize = 2 * (WSB_BYTE_SIZE_GUID + //Id
|
|
WSB_BYTE_SIZE_GUID + //ntmsId
|
|
WSB_BYTE_SIZE_GUID + //soragePoolId
|
|
4 + //nme
|
|
4 + //brCode
|
|
WSB_BYTE_SIZE_SHORT+ //tpe
|
|
WSB_BYTE_SIZE_FILETIME + //lastUpdate
|
|
WSB_BYTE_SIZE_LONG + //lastError
|
|
WSB_BYTE_SIZE_BOOL + //m_RecallOnly
|
|
WSB_BYTE_SIZE_LONGLONG + //m_freeBytes
|
|
WSB_BYTE_SIZE_LONGLONG + //m_Capacity
|
|
WSB_BYTE_SIZE_SHORT) + //nextRemoteDataSet
|
|
|
|
WSB_BYTE_SIZE_BOOL + //m_Recreate
|
|
WSB_BYTE_SIZE_LONGLONG + //m_LocicalFreeSpace
|
|
|
|
3 * (WSB_BYTE_SIZE_GUID + //m_RmsMediaId
|
|
4 + //m_Name
|
|
4 + //m_BarCode
|
|
WSB_BYTE_SIZE_FILETIME + //m_Update
|
|
WSB_BYTE_SIZE_LONG + //m_LastError
|
|
WSB_BYTE_SIZE_SHORT ); //nextRemoteDataSet
|
|
|
|
// NOTE:
|
|
//
|
|
// The next line that calculates the max record size for media info has a BAD bug in it - Windows Bugs 407340.
|
|
// The macro SEG_DB_MAX_MEDIA_NAME_LEN and SEG_DB_MAX_MEDIA_BAR_CODE_LEN are defined without parenthesis - see in segdb.h
|
|
// As a result, the max size is only 711 bytes instead of 1751 as it should be !!
|
|
//
|
|
// It is NOT fixed since there are too many existing installations with the wrong record size...
|
|
// This bug has implications around the code - look for "Windows Bugs 407340" comments throughout the HSM code
|
|
//
|
|
m_RecInfo[1].MaxSize = m_RecInfo[1].MinSize + 5 * SEG_DB_MAX_MEDIA_NAME_LEN + 5 * SEG_DB_MAX_MEDIA_BAR_CODE_LEN;
|
|
m_RecInfo[1].nKeys = 1;
|
|
|
|
memSize = m_RecInfo[1].nKeys * sizeof(IDB_KEY_INFO);
|
|
m_RecInfo[1].Key = (IDB_KEY_INFO*)WsbAlloc(memSize);
|
|
WsbAffirm(0 != m_RecInfo[1].Key, E_FAIL);
|
|
ZeroMemory(m_RecInfo[1].Key, memSize);
|
|
|
|
m_RecInfo[1].Key[0].Type = MEDIA_INFO_KEY_TYPE;
|
|
m_RecInfo[1].Key[0].Size = WSB_BYTE_SIZE_GUID;
|
|
m_RecInfo[1].Key[0].Flags = IDB_KEY_FLAG_PRIMARY;
|
|
|
|
// Bag information
|
|
m_RecInfo[2].Type = HSM_BAG_INFO_REC_TYPE;
|
|
m_RecInfo[2].EntityClassId = CLSID_CBagInfo;
|
|
m_RecInfo[2].Flags = 0;
|
|
m_RecInfo[2].MinSize = (2 * WSB_BYTE_SIZE_GUID) +
|
|
(2 * WSB_BYTE_SIZE_LONGLONG) + (2 * WSB_BYTE_SIZE_USHORT) +
|
|
WSB_BYTE_SIZE_FILETIME + WSB_BYTE_SIZE_SHORT;
|
|
m_RecInfo[2].MaxSize = m_RecInfo[2].MinSize;
|
|
m_RecInfo[2].nKeys = 1;
|
|
|
|
memSize = m_RecInfo[2].nKeys * sizeof(IDB_KEY_INFO);
|
|
m_RecInfo[2].Key = (IDB_KEY_INFO*)WsbAlloc(memSize);
|
|
WsbAffirm(0 != m_RecInfo[2].Key, E_FAIL);
|
|
ZeroMemory(m_RecInfo[2].Key, memSize);
|
|
|
|
m_RecInfo[2].Key[0].Type = BAG_INFO_KEY_TYPE;
|
|
m_RecInfo[2].Key[0].Size = WSB_BYTE_SIZE_GUID;
|
|
m_RecInfo[2].Key[0].Flags = IDB_KEY_FLAG_PRIMARY;
|
|
|
|
// Bag holes
|
|
m_RecInfo[3].Type = HSM_BAG_HOLE_REC_TYPE;
|
|
m_RecInfo[3].EntityClassId = CLSID_CBagHole;
|
|
m_RecInfo[3].Flags = 0;
|
|
m_RecInfo[3].MinSize = WSB_BYTE_SIZE_GUID +
|
|
2 * WSB_BYTE_SIZE_LONGLONG;
|
|
m_RecInfo[3].MaxSize = m_RecInfo[3].MinSize;
|
|
m_RecInfo[3].nKeys = 1;
|
|
|
|
memSize = m_RecInfo[3].nKeys * sizeof(IDB_KEY_INFO);
|
|
m_RecInfo[3].Key = (IDB_KEY_INFO*)WsbAlloc(memSize);
|
|
WsbAffirm(0 != m_RecInfo[3].Key, E_FAIL);
|
|
ZeroMemory(m_RecInfo[3].Key, memSize);
|
|
|
|
m_RecInfo[3].Key[0].Type = BAG_HOLE_KEY_TYPE;
|
|
m_RecInfo[3].Key[0].Size = WSB_BYTE_SIZE_GUID +
|
|
WSB_BYTE_SIZE_LONGLONG;
|
|
m_RecInfo[3].Key[0].Flags = IDB_KEY_FLAG_DUP_ALLOWED;
|
|
|
|
// Volume assignment
|
|
m_RecInfo[4].Type = HSM_VOL_ASSIGN_REC_TYPE;
|
|
m_RecInfo[4].EntityClassId = CLSID_CVolAssign;
|
|
m_RecInfo[4].Flags = 0;
|
|
m_RecInfo[4].MinSize = 2 * WSB_BYTE_SIZE_GUID +
|
|
2 * WSB_BYTE_SIZE_LONGLONG;
|
|
m_RecInfo[4].MaxSize = m_RecInfo[4].MinSize;
|
|
m_RecInfo[4].nKeys = 1;
|
|
|
|
memSize = m_RecInfo[4].nKeys * sizeof(IDB_KEY_INFO);
|
|
m_RecInfo[4].Key = (IDB_KEY_INFO*)WsbAlloc(memSize);
|
|
WsbAffirm(0 != m_RecInfo[4].Key, E_FAIL);
|
|
ZeroMemory(m_RecInfo[4].Key, memSize);
|
|
|
|
m_RecInfo[4].Key[0].Type = VOL_ASSIGN_KEY_TYPE;
|
|
m_RecInfo[4].Key[0].Size = WSB_BYTE_SIZE_GUID +
|
|
WSB_BYTE_SIZE_LONGLONG;
|
|
m_RecInfo[4].Key[0].Flags = IDB_KEY_FLAG_DUP_ALLOWED;
|
|
|
|
// Create the new DB
|
|
WsbAssertHr(Create(path));
|
|
CreateFlag = TRUE;
|
|
|
|
} else if (hr == STG_E_FILENOTFOUND) {
|
|
|
|
// DB doesn't exist, but we're not suppose to create it
|
|
WsbLogEvent(WSB_MESSAGE_IDB_OPEN_FAILED, 0, NULL,
|
|
WsbQuickString(WsbAbbreviatePath(path, 120)), NULL );
|
|
hr = WSB_E_IDB_FILE_NOT_FOUND;
|
|
}
|
|
} WsbCatch(hr);
|
|
|
|
if (pCreateFlag) {
|
|
*pCreateFlag = CreateFlag;
|
|
}
|
|
|
|
WsbTraceOut(OLESTR("CSegDb::Initialize"),
|
|
OLESTR("hr = %ls, path = <%ls>, CreateFlag = <%ls>"),
|
|
WsbHrAsString(hr), WsbAbbreviatePath(path, 120),
|
|
WsbPtrToBoolAsString(pCreateFlag));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CSegDb::Load(
|
|
IN IStream* pStream
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IPersistStream::Load().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
WsbAffirmHr(CWsbDb::Load(pStream));
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CSegDb::Save(
|
|
IN IStream* pStream,
|
|
IN BOOL clearDirty
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IPersistStream::Save().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
WsbAffirmHr(CWsbDb::Save(pStream, clearDirty));
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CSegDb::SegAdd
|
|
(
|
|
IN IWsbDbSession* pDbSession,
|
|
IN GUID BagId,
|
|
IN LONGLONG SegStartLoc,
|
|
IN LONGLONG SegLen,
|
|
IN GUID MediaId,
|
|
IN LONGLONG mediaStart,
|
|
IN BOOL indirectRecord
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
ISegDb::SegAdd
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CSegDb::SegAdd"),
|
|
OLESTR("GUID = %ls, SegStartLoc = %I64u, SegLen = %I64u"),
|
|
WsbGuidAsString(BagId), SegStartLoc, SegLen);
|
|
|
|
try {
|
|
BOOL found = FALSE;
|
|
CComPtr<ISegRec> pSegRec;
|
|
GUID l_BagId = GUID_NULL;
|
|
LONGLONG l_SegStartLoc = 0;
|
|
LONGLONG l_SegLen = 0;
|
|
USHORT l_SegFlags = SEG_REC_NONE;
|
|
GUID l_MediaId = GUID_NULL;
|
|
LONGLONG l_MediaStart = 0;
|
|
|
|
WsbAffirmHr(GetEntity(pDbSession, HSM_SEG_REC_TYPE, IID_ISegRec,
|
|
(void **)&pSegRec));
|
|
WsbAffirmHr(pSegRec->SetSegmentRecord(BagId, SegStartLoc,
|
|
0, 0, GUID_NULL, 0 ));
|
|
|
|
// Look for a segment to which to append this one
|
|
hr = pSegRec->FindLTE();
|
|
if (WSB_E_NOTFOUND == hr) {
|
|
hr = S_OK;
|
|
} else {
|
|
WsbAffirmHr(pSegRec->GetSegmentRecord(&l_BagId, &l_SegStartLoc, &l_SegLen, &l_SegFlags,
|
|
&l_MediaId, &l_MediaStart));
|
|
if (SEG_EXPAND_OK(l_BagId, l_SegStartLoc, l_SegLen,
|
|
BagId, SegStartLoc, SegLen) &&
|
|
IsEqualGUID(MediaId, l_MediaId)) {
|
|
WsbTrace(OLESTR("CSegDb::SegAdd: Found SegmentRecord: StartLoc = %I64u, Len = %I64u\n"),
|
|
l_SegStartLoc, l_SegLen);
|
|
found = TRUE;
|
|
}
|
|
}
|
|
|
|
if (found) {
|
|
// Append this segment to the existing record
|
|
l_SegLen = (SegStartLoc - l_SegStartLoc) + SegLen;
|
|
WsbTrace(OLESTR("CSegDb::SegAdd: new SegLen = %I64u\n"), l_SegLen);
|
|
} else {
|
|
// Create a new segment record
|
|
l_SegStartLoc = SegStartLoc;
|
|
l_SegLen = SegLen;
|
|
if (indirectRecord) {
|
|
l_SegFlags = SEG_REC_INDIRECT_RECORD;
|
|
} else {
|
|
l_SegFlags = SEG_REC_NONE;
|
|
}
|
|
l_MediaId = MediaId;
|
|
l_MediaStart = mediaStart;
|
|
WsbAffirmHr(pSegRec->MarkAsNew());
|
|
WsbTrace(OLESTR("CSegDb::SegAdd: add new segment\n"));
|
|
}
|
|
WsbAffirmHr(pSegRec->SetSegmentRecord(BagId, l_SegStartLoc,
|
|
l_SegLen, l_SegFlags, l_MediaId, l_MediaStart ));
|
|
|
|
WsbAffirmHr(pSegRec->Write());
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CSegDb::SegAdd"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CSegDb::SegFind
|
|
(
|
|
IN IWsbDbSession* pDbSession,
|
|
IN GUID BagId,
|
|
IN LONGLONG SegStartLoc,
|
|
IN LONGLONG SegLen,
|
|
OUT ISegRec** ppISegRec
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
ISegDb::SegFind
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CSegDb::SegFind"),
|
|
OLESTR("GUID = <%ls>, SegStartLoc = <%I64u>, SegLen = <%I64u>"),
|
|
WsbGuidAsString(BagId),
|
|
SegStartLoc,
|
|
SegLen);
|
|
|
|
try {
|
|
CComPtr<ISegRec> pSegRec;
|
|
GUID l_BagId;
|
|
LONGLONG l_SegStartLoc;
|
|
LONGLONG l_SegLen;
|
|
USHORT l_SegFlags;
|
|
GUID l_MediaId;
|
|
LONGLONG l_MediaStart;
|
|
|
|
WsbAffirm(ppISegRec != NULL, E_POINTER);
|
|
WsbAffirmHr(GetEntity(pDbSession, HSM_SEG_REC_TYPE, IID_ISegRec,
|
|
(void **)&pSegRec));
|
|
WsbAffirmHr(pSegRec->SetSegmentRecord(BagId, SegStartLoc,
|
|
0, 0, GUID_NULL, 0 ));
|
|
|
|
// Look for a segment that contains this one
|
|
WsbTrace(OLESTR("Finding SegmentRecord: <%ls>, <%I64u>, <%I64u>\n"),
|
|
WsbGuidAsString(BagId),
|
|
SegStartLoc,
|
|
SegLen);
|
|
WsbAffirmHr(pSegRec->FindLTE());
|
|
|
|
// We found a record, see if it's the right one
|
|
WsbAffirmHr(pSegRec->GetSegmentRecord(&l_BagId, &l_SegStartLoc,
|
|
&l_SegLen, &l_SegFlags, &l_MediaId, &l_MediaStart));
|
|
if (SEG_CONTAINS(l_BagId, l_SegStartLoc, l_SegLen,
|
|
BagId, SegStartLoc, SegLen)) {
|
|
*ppISegRec = pSegRec;
|
|
pSegRec.p->AddRef();
|
|
} else {
|
|
hr = WSB_E_NOTFOUND;
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CSegDb::SegFind"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CSegDb::SegSubtract
|
|
(
|
|
IN IWsbDbSession* pDbSession,
|
|
IN GUID BagId,
|
|
IN LONGLONG SegStartLoc,
|
|
IN LONGLONG SegLen
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
ISegDb::SegSubtract
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CSegDb::SegSubtract"),
|
|
OLESTR("GUID = <%ls>, SegStartLoc = <%I64u>, SegLen = <%I64u>"),
|
|
WsbGuidAsString(BagId),
|
|
SegStartLoc,
|
|
SegLen);
|
|
|
|
try {
|
|
GUID l_BagId;
|
|
LONGLONG l_SegStartLoc;
|
|
LONGLONG l_SegLen;
|
|
USHORT l_SegFlags;
|
|
GUID l_MediaId;
|
|
LONGLONG l_MediaStart;
|
|
CComPtr<ISegRec> pSegRec;
|
|
|
|
// Find the segment record
|
|
WsbAffirmHr(SegFind(pDbSession, BagId, SegStartLoc, SegLen, &pSegRec));
|
|
|
|
// Get the current data
|
|
WsbAffirmHr(pSegRec->GetSegmentRecord(&l_BagId, &l_SegStartLoc,
|
|
&l_SegLen, &l_SegFlags, &l_MediaId, &l_MediaStart));
|
|
|
|
// Determine where the hole is
|
|
if (l_SegStartLoc == SegStartLoc && l_SegLen == SegLen) {
|
|
// Hole is the entire segment -- delete it
|
|
WsbAffirmHr(pSegRec->Remove());
|
|
|
|
} else if (l_SegStartLoc == SegStartLoc) {
|
|
// Hole is at the beginning of the segment. Just update the
|
|
// existing segment
|
|
l_SegStartLoc += SegLen;
|
|
l_MediaStart += SegLen;
|
|
WsbAffirmHr(pSegRec->SetSegmentRecord(BagId, l_SegStartLoc,
|
|
l_SegLen, l_SegFlags, l_MediaId, l_MediaStart ));
|
|
WsbAffirmHr(pSegRec->Write());
|
|
|
|
} else if ((l_SegStartLoc + l_SegLen) == (SegStartLoc + SegLen)) {
|
|
// Hole is at the end of the segment. Just update the
|
|
// existing segment
|
|
l_SegLen -= SegLen;
|
|
WsbAffirmHr(pSegRec->SetSegmentRecord(BagId, l_SegStartLoc,
|
|
l_SegLen, l_SegFlags, l_MediaId, l_MediaStart ));
|
|
WsbAffirmHr(pSegRec->Write());
|
|
|
|
} else {
|
|
// Hole is in the middle of the segment. Update the
|
|
// existing record to be the first part.
|
|
LONGLONG oldLen = l_SegLen;
|
|
LONGLONG offset = (SegStartLoc + SegLen) - l_SegStartLoc;
|
|
BOOL bIndirect = FALSE;
|
|
|
|
l_SegLen = SegStartLoc - l_SegStartLoc;
|
|
WsbAffirmHr(pSegRec->SetSegmentRecord(BagId, l_SegStartLoc,
|
|
l_SegLen, l_SegFlags, l_MediaId, l_MediaStart ));
|
|
WsbAffirmHr(pSegRec->Write());
|
|
|
|
// Create a new record for the second part.
|
|
l_SegLen -= offset;
|
|
l_SegStartLoc += offset;
|
|
l_MediaStart += offset;
|
|
if (l_SegFlags & SEG_REC_INDIRECT_RECORD) {
|
|
bIndirect = TRUE;
|
|
}
|
|
WsbAffirmHr(SegAdd(pDbSession, BagId, l_SegStartLoc, l_SegLen, l_MediaId,
|
|
l_MediaStart, bIndirect));
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CSegDb::SegSubtract"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CSegDb::VolAssignAdd
|
|
(
|
|
IN IWsbDbSession* pDbSession,
|
|
IN GUID BagId,
|
|
IN LONGLONG SegStartLoc,
|
|
IN LONGLONG SegLen,
|
|
IN GUID VolId
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
ISegDb::VolAssignAdd
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CSegDb::VolAssignAdd"),
|
|
OLESTR("GUID = <%ls>, SegStartLoc = <%I64u>, SegLen = <%I64u>"),
|
|
WsbGuidAsString(BagId),
|
|
SegStartLoc,
|
|
SegLen);
|
|
|
|
try {
|
|
BOOL found = FALSE;
|
|
CComPtr<IVolAssign> pVolAssign;
|
|
GUID l_BagId = GUID_NULL;
|
|
LONGLONG l_SegStartLoc = 0;
|
|
LONGLONG l_SegLen = 0;
|
|
GUID l_VolId = GUID_NULL;
|
|
|
|
WsbAffirmHr(GetEntity(pDbSession, HSM_VOL_ASSIGN_REC_TYPE, IID_IVolAssign,
|
|
(void **)&pVolAssign));
|
|
WsbAffirmHr(pVolAssign->SetVolAssign(BagId, SegStartLoc,
|
|
0, GUID_NULL));
|
|
|
|
// Look for a segment to which to append this one
|
|
WsbTrace(OLESTR("Finding VolAssign Record: <%ls>, <%I64u>, <%I64u>\n"),
|
|
WsbGuidAsString(BagId),
|
|
SegStartLoc,
|
|
SegLen);
|
|
hr = pVolAssign->FindLTE();
|
|
if (WSB_E_NOTFOUND == hr) {
|
|
hr = S_OK;
|
|
} else {
|
|
WsbAffirmHr(pVolAssign->GetVolAssign(&l_BagId, &l_SegStartLoc,
|
|
&l_SegLen, &l_VolId));
|
|
if (SEG_APPEND_OK(l_BagId, l_SegStartLoc, l_SegLen,
|
|
BagId, SegStartLoc, SegLen) && IsEqualGUID(l_VolId, VolId)) {
|
|
found = TRUE;
|
|
}
|
|
}
|
|
|
|
if (found) {
|
|
// Append this segment to the existing record
|
|
l_SegLen += SegLen;
|
|
} else {
|
|
// Create a new record
|
|
l_SegStartLoc = SegStartLoc;
|
|
l_SegLen = SegLen;
|
|
l_VolId = VolId;
|
|
WsbAffirmHr(pVolAssign->MarkAsNew());
|
|
}
|
|
WsbAffirmHr(pVolAssign->SetVolAssign(BagId, l_SegStartLoc,
|
|
l_SegLen, l_VolId));
|
|
|
|
WsbTrace(OLESTR("Writing VolAssign Record: <%ls>, <%I64u>, <%I64u>\n"),
|
|
WsbGuidAsString(BagId),
|
|
l_SegStartLoc,
|
|
l_SegLen);
|
|
WsbAffirmHr(pVolAssign->Write());
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CSegDb::VolAssignAdd"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CSegDb::VolAssignFind
|
|
(
|
|
IN IWsbDbSession* pDbSession,
|
|
IN GUID BagId,
|
|
IN LONGLONG SegStartLoc,
|
|
IN LONGLONG SegLen,
|
|
OUT IVolAssign** ppIVolAssign
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
ISegDb::VolAssignFind
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CSegDb::VolAssignFind"),
|
|
OLESTR("GUID = <%ls>, SegStartLoc = <%I64u>, SegLen = <%I64u>"),
|
|
WsbGuidAsString(BagId),
|
|
SegStartLoc,
|
|
SegLen);
|
|
|
|
try {
|
|
CComPtr<IVolAssign> pVolAssign;
|
|
GUID l_BagId;
|
|
LONGLONG l_SegStartLoc;
|
|
LONGLONG l_SegLen;
|
|
GUID l_VolId;
|
|
|
|
WsbAffirm(ppIVolAssign != NULL, E_POINTER);
|
|
WsbAffirmHr(GetEntity(pDbSession, HSM_VOL_ASSIGN_REC_TYPE, IID_IVolAssign,
|
|
(void **)&pVolAssign));
|
|
WsbAffirmHr(pVolAssign->SetVolAssign(BagId, SegStartLoc, 0, GUID_NULL));
|
|
|
|
// Look for a segment that contains this one
|
|
WsbTrace(OLESTR("Finding VolAssign Record: <%ls>, <%I64u>, <%I64u>\n"),
|
|
WsbGuidAsString(BagId),
|
|
SegStartLoc,
|
|
SegLen);
|
|
WsbAffirmHr(pVolAssign->FindLTE());
|
|
|
|
// We found a record, see if it's the right one
|
|
WsbAffirmHr(pVolAssign->GetVolAssign(&l_BagId, &l_SegStartLoc,
|
|
&l_SegLen, &l_VolId));
|
|
if (SEG_CONTAINS(l_BagId, l_SegStartLoc, l_SegLen,
|
|
BagId, SegStartLoc, SegLen)) {
|
|
*ppIVolAssign = pVolAssign;
|
|
pVolAssign.p->AddRef();
|
|
} else {
|
|
hr = WSB_E_NOTFOUND;
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CSegDb::VolAssignFind"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CSegDb::VolAssignSubtract
|
|
(
|
|
IN IWsbDbSession* pDbSession,
|
|
IN GUID BagId,
|
|
IN LONGLONG SegStartLoc,
|
|
IN LONGLONG SegLen
|
|
)
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
ISegDb::VolAssignSubtract
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CSegDb::VolAssignSubtract"),
|
|
OLESTR("GUID = <%ls>, SegStartLoc = <%I64u>, SegLen = <%I64u>"),
|
|
WsbGuidAsString(BagId),
|
|
SegStartLoc,
|
|
SegLen);
|
|
|
|
try {
|
|
GUID l_BagId;
|
|
LONGLONG l_SegStartLoc;
|
|
LONGLONG l_SegLen;
|
|
GUID l_VolId;
|
|
CComPtr<IVolAssign> pVolAssign;
|
|
|
|
// Find the segment record
|
|
WsbAffirmHr(VolAssignFind(pDbSession, BagId, SegStartLoc, SegLen, &pVolAssign));
|
|
|
|
// Get the current data
|
|
WsbAffirmHr(pVolAssign->GetVolAssign(&l_BagId, &l_SegStartLoc,
|
|
&l_SegLen, &l_VolId));
|
|
|
|
// Determine where the hole is
|
|
if (l_SegStartLoc == SegStartLoc && l_SegLen == SegLen) {
|
|
// Hole is the entire segment -- delete it
|
|
WsbAffirmHr(pVolAssign->Remove());
|
|
|
|
} else if (l_SegStartLoc == SegStartLoc) {
|
|
// Hole is at the beginning of the segment. Just update the
|
|
// existing segment
|
|
l_SegStartLoc += SegLen;
|
|
WsbAffirmHr(pVolAssign->SetVolAssign(BagId, l_SegStartLoc,
|
|
l_SegLen, l_VolId));
|
|
WsbAffirmHr(pVolAssign->Write());
|
|
|
|
} else if ((l_SegStartLoc + l_SegLen) == (SegStartLoc + SegLen)) {
|
|
// Hole is at the end of the segment. Just update the
|
|
// existing segment
|
|
l_SegLen -= SegLen;
|
|
WsbAffirmHr(pVolAssign->SetVolAssign(BagId, l_SegStartLoc,
|
|
l_SegLen, l_VolId));
|
|
WsbAffirmHr(pVolAssign->Write());
|
|
|
|
} else {
|
|
// Hole is in the middle of the segment. Update the
|
|
// existing record to be the first part.
|
|
LONGLONG oldLen = l_SegLen;
|
|
LONGLONG offset = (SegStartLoc + SegLen) - l_SegStartLoc;
|
|
|
|
l_SegLen = SegStartLoc - l_SegStartLoc;
|
|
WsbAffirmHr(pVolAssign->SetVolAssign(BagId, l_SegStartLoc,
|
|
l_SegLen, l_VolId));
|
|
WsbAffirmHr(pVolAssign->Write());
|
|
|
|
// Create a new record for the second part.
|
|
l_SegLen -= offset;
|
|
l_SegStartLoc += offset;
|
|
WsbAffirmHr(VolAssignAdd(pDbSession, BagId, l_SegStartLoc, l_SegLen,
|
|
l_VolId));
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CSegDb::VolAssignSubtract"), OLESTR("hr = <%ls>"),WsbHrAsString(S_OK));
|
|
return(hr);
|
|
}
|