|
|
//+--------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1992.
//
// File: wdfxact.cxx
//
// Contents: CWrappedDocFile transactioning methods
//
// History: 22-Jan-92 DrewB Created
//
//---------------------------------------------------------------
#include <dfhead.cxx>
#pragma hdrstop
#include <sstream.hxx>
#include <tstream.hxx>
#include <dfdeb.hxx>
//+--------------------------------------------------------------
//
// Member: CWrappedDocFile::BeginCommit, public
//
// Synopsis: Allocates commit resources for two-phase commit
//
// Arguments: [dwFlags] - Flags
//
// Returns: Appropriate status code
//
// History: 06-Jan-92 DrewB Created
//
//---------------------------------------------------------------
SCODE CWrappedDocFile::BeginCommit(DWORD const dwFlags) { SCODE sc; #ifdef INDINST
DFSIGNATURE sigNew; #endif
olDebugOut((DEB_ITRACE, "In CWrappedDocFile::BeginCommit(%lX)\n", dwFlags));
olAssert(_pdfBase != NULL); olAssert(P_TRANSACTED(_df));
#if DBG == 1
if (!HaveResource(DBR_XSCOMMITS, 1)) olErr(EH_Err, STG_E_ABNORMALAPIEXIT); #endif
_fBeginCommit = TRUE; #ifdef INDINST
_ppubdf->GetNewSignature(&sigNew); olChk(_pdfBase->BeginCommitFromChild(_ulChanged, NULL, _sigBase, sigNew, dwFlags, _ppubdf)); // INDINST - Ownership of dirty and changed?
if (P_INDEPENDENT(_df) && _pdfParent) olChkTo(EH_Begin, _pdfParent->BeginCommitFromChild(_ulChanged, _pdfBase, _sigBase, sigNew, dwFlags, _ppubdf)); _sigBaseOld = _sigBase; _sigCombinedOld = _sigCombined; _sigBase = _sigCombined = sigNew; #else
olChk(_pdfBase->BeginCommitFromChild(_ulChanged, dwFlags, this)); #endif
olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::BeginCommit\n")); return S_OK;
#ifdef INDINST
EH_Begin: _pdfBase->EndCommitFromChild(DF_ABORT); #endif
EH_Err: return sc; }
//+--------------------------------------------------------------
//
// Member: CWrappedDocFile::EndCommit, public
//
// Synopsis: Performs actual commit/abort for two-phase commit
//
// Arguments: [df] - COMMIT/ABORT
//
// Returns: Appropriate status code
//
// History: 06-Jan-92 DrewB Created
//
//---------------------------------------------------------------
void CWrappedDocFile::EndCommit(DFLAGS const df) { olDebugOut((DEB_ITRACE, "In CWrappedDocFile::EndCommit(%X)\n", df));
olAssert(P_TRANSACTED(_df));
if (!_fBeginCommit) return; _fBeginCommit = FALSE;
#if DBG == 1
if (P_COMMIT(df)) ModifyResLimit(DBR_XSCOMMITS, 1); #endif
_pdfBase->EndCommitFromChild(df, this); #ifdef INDINST
if (P_INDEPENDENT(_df) && _pdfParent) olVerSucc(_pdfParent->EndCommitFromChild(df)); #endif
if (P_COMMIT(df)) { // These are nulled because the memory should be gone
_ulChanged.Unlink(); SetClean(); } else { #ifdef INDINST
_sigBase = _sigBaseOld; _sigCombined = _sigCombinedOld; #endif
} olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::EndCommit\n")); }
//+--------------------------------------------------------------
//
// Member: CWrappedDocFile::Revert, public
//
// Synopsis: Transaction level has requested revert
//
// History: 06-Jan-92 DrewB Created
//
//---------------------------------------------------------------
void CWrappedDocFile::Revert(void) { CUpdate *pud;
olDebugOut((DEB_ITRACE, "In CWrappedDocFile %p::Revert()\n", this)); for (pud = _ulChanged.GetTail(); pud; pud = pud->GetPrev()) RevertUpdate(pud); _ulChanged.Empty(); olVerSucc(SetInitialState(BP_TO_P(PDocFile *, _pdfBase))); SetClean();
olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::Revert\n")); }
//+--------------------------------------------------------------
//
// Member: CWrappedDocFile::BeginCommitFromChild, public
//
// Synopsis: Start two-phase commit, requested by child
//
// Arguments: [ulChanged] - Change list
// [dwFlags] - Flags controlling commit
// [pdfChild] - Child object
//
// Returns: Appropriate status code
//
// History: 06-Jan-92 DrewB Created
//
//---------------------------------------------------------------
SCODE CWrappedDocFile::BeginCommitFromChild(CUpdateList &ulChanged, DWORD const dwFlags, CWrappedDocFile *pdfChild) { CUpdate *pud, *pudNext;
olDebugOut((DEB_ITRACE, "In CWrappedDocFile::BeginCommitFromChild:%p(" "%p, %lX, %p)\n", this, ulChanged.GetHead(), dwFlags, pdfChild));
UNREFERENCED_PARM(pdfChild);
olAssert(P_TRANSACTED(_df)); olAssert(_tssDeletedHolder.GetHead() == NULL);
_ulChangedHolder = ulChanged; _ulChangedOld = _ulChanged;
for (pud = ulChanged.GetHead(); pud; pud = pudNext) { if (pud->IsRename()) _ppubdf->RenameChild(pud->GetOriginalName(), GetName(), pud->GetCurrentName()); else if (pud->IsDelete()) { PTSetMember *ptsm; if ((ptsm = _ppubdf->FindXSMember(pud->GetOriginalName(), GetName())) != NULL) { olAssert(ptsm->GetName() != DF_NOLUID && aMsg("Can't destroy NOLUID XSM")); // Take a reference because RemoveXSMember
// will call Release
ptsm->AddRef(); _ppubdf->RemoveXSMember(ptsm); _tssDeletedHolder.AddMember(ptsm); } } else if (pud->IsCreate()) olVerSucc(CreateFromUpdate(pud, this, DF_WRITE | DF_NOUPDATE | DF_TRANSACTED)); pudNext = pud->GetNext(); _ulChanged.Append(pud); }
olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::BeginCommitFromChild\n")); return S_OK; }
//+--------------------------------------------------------------
//
// Member: CWrappedDocFile::EndCommitFromChild
//
// Synopsis: Ends two-phase commit, requested by child
//
// Arguments: [df] - COMMIT/ABORT
// [pdfChild] - Child object
//
// Returns: Appropriate status code
//
// History: 06-Jan-92 DrewB Created
//
//---------------------------------------------------------------
void CWrappedDocFile::EndCommitFromChild(DFLAGS const df, CWrappedDocFile *pdfChild) { PTSetMember *ptsm; CUpdate *pud;
olDebugOut((DEB_ITRACE, "In CWrappedDocFile::EndCommitFromChild:%p(" "%X, %p)\n", this, df, pdfChild));
olAssert(P_TRANSACTED(_df));
if (!P_COMMIT(df)) { // Restore our update list
_ulChanged = _ulChangedOld;
// Unconcat _ulChanged and ulChanged
if (_ulChanged.GetTail()) _ulChanged.GetTail()->SetNext(NULL); if (_ulChangedHolder.GetHead()) _ulChangedHolder.GetHead()->SetPrev(NULL);
// Back out updates
for (pud = _ulChangedHolder.GetTail(); pud; pud = pud->GetPrev()) if (pud->IsCreate()) { // We need to do two things:
//
// Break any SetBase links that might have been created
//
// Return newly created objects to the creators so
// that they can be returned to the preallocation
// pool
if ((pud->GetFlags() & (ULF_TYPEFLAGS & STGTY_REAL)) == STGTY_STORAGE) { CWrappedDocFile *pwdf = (CWrappedDocFile *)pud->GetXSM(); CWrappedDocFile *pwdfBase;
if (pwdf != NULL && (pwdfBase = (CWrappedDocFile *)pwdf->GetBase()) != NULL) { // Increase ref count because SetBase will release
pwdfBase->AddRef(); pwdf->SetBase(NULL); ReturnDocFile(pwdfBase); } } else { CTransactedStream *ptstm = (CTransactedStream *)pud-> GetXSM(); CTransactedStream *ptstmBase;
olAssert((pud->GetFlags() & (ULF_TYPEFLAGS & STGTY_REAL)) == STGTY_STREAM); if (ptstm != NULL && (ptstmBase = (CTransactedStream *)ptstm->GetBase()) != NULL) { // Increase ref count because SetBase will release
ptstmBase->AddRef(); ptstm->SetBase(NULL); ReturnStream(ptstmBase); } } } else if (pud->IsDelete()) { // We use GetName() as the tree because we know that
// only immediate children can show up in delete records
if ((ptsm = _tssDeletedHolder.FindName(pud->GetOriginalName(), GetName())) != NULL) { _tssDeletedHolder.RemoveMember(ptsm); _ppubdf->InsertXSMember(ptsm); // Release the reference we took in BeginCommitFromChild
// because InsertXSMember takes a reference
ptsm->Release(); } } else if (pud->IsRename()) { // Roll back renames
olAssert(_ppubdf->FindXSMember(pud->GetOriginalName(), GetName()) == NULL && aMsg("Abort commit rename precondition"));
_ppubdf->RenameChild(pud->GetCurrentName(), GetName(), pud->GetOriginalName());
olAssert(_ppubdf->FindXSMember(pud->GetCurrentName(), GetName()) == NULL && aMsg("Abort commit rename postcondition")); } } else { // Finalize creations
for (pud = _ulChangedHolder.GetHead(); pud; pud = pud->GetNext()) if (pud->IsCreate()) { // Since the object pointed to by GetBase is at our level,
// we know it is transacted so we can safely cast to
// PTSetMember
if ((pud->GetFlags() & (ULF_TYPEFLAGS & STGTY_REAL)) == STGTY_STORAGE) { ptsm = (CWrappedDocFile *) ((CWrappedDocFile *)pud->GetXSM())->GetBase(); } else { olAssert((pud->GetFlags() & (ULF_TYPEFLAGS & STGTY_REAL)) == STGTY_STREAM); ptsm = (CTransactedStream *) ((CTransactedStream *)pud->GetXSM())->GetBase(); } pud->SetXSM(ptsm); }
// Finalize deletions
while (ptsm = _tssDeletedHolder.GetHead()) { olAssert(ptsm->GetName() != DF_NOLUID && aMsg("Can't destroy NOLUID XSM")); _ppubdf->DestroyChild(ptsm->GetName()); _tssDeletedHolder.RemoveMember(ptsm); ptsm->Release(); }
// Pick up state information
TIME_T tm;
if (pdfChild->GetDirty() & DIRTY_CREATETIME) { olVerSucc(pdfChild->GetTime(WT_CREATION, &tm)); olVerSucc(SetTime(WT_CREATION, tm)); } if (pdfChild->GetDirty() & DIRTY_MODIFYTIME) { olVerSucc(pdfChild->GetTime(WT_MODIFICATION, &tm)); olVerSucc(SetTime(WT_MODIFICATION, tm)); } if (pdfChild->GetDirty() & DIRTY_ACCESSTIME) { olVerSucc(pdfChild->GetTime(WT_ACCESS, &tm)); olVerSucc(SetTime(WT_ACCESS, tm)); } if (pdfChild->GetDirty() & DIRTY_CLASS) { CLSID cls; olVerSucc(pdfChild->GetClass(&cls)); olVerSucc(SetClass(cls)); } if (pdfChild->GetDirty() & DIRTY_STATEBITS) { DWORD dwState; olVerSucc(pdfChild->GetStateBits(&dwState)); olVerSucc(SetStateBits(dwState, 0xffffffff)); } }
// Forget temporary commit lists
_ulChangedOld.Unlink(); _ulChangedHolder.Unlink();
olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::EndCommitFromChild\n")); }
//+--------------------------------------------------------------
//
// Member: CWrappedDocFile::GetSignature, public
//
// Synopsis: Returns signature
//
// Returns: Appropriate status code
//
// History: 06-Jan-92 DrewB Created
//
//---------------------------------------------------------------
#ifdef INDINST
void CWrappedDocFile::GetSignature(DFSIGNATURE *psig) { olDebugOut((DEB_ITRACE, "In CWrappedDocFile::GetSignature()\n")); olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::GetSignature => %ld\n", _sigCombined)); *psig = _sigCombined; } #endif
//+--------------------------------------------------------------
//
// Member: CWrappedDocFile::SetSignature, public
//
// Synopsis: Sets the signature
//
// Arguments: [sig] - Signature
//
// Returns: Appropriate status code
//
// History: 04-Feb-92 DrewB Created
//
//---------------------------------------------------------------
#ifdef INDINST
void CWrappedDocFile::SetSignature(DFSIGNATURE sig) { olDebugOut((DEB_ITRACE, "In CWrappedDocFile::SetSignature(%ld)\n", sig)); _sigCombined = sig; olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::SetSignature\n")); } #endif
//+--------------------------------------------------------------
//
// Member: CWrappedDocFile::SetBase, public
//
// Synopsis: Sets Base pointer
//
// Arguments: [pdf] - New base
//
// Returns: Appropriate status code
//
// History: 06-Jan-92 DrewB Created
//
//---------------------------------------------------------------
SCODE CWrappedDocFile::SetBase(PDocFile *pdf) { SCODE sc = S_OK;
olDebugOut((DEB_ITRACE, "In CWrappedDocFile::SetBase(%p)\n", pdf)); olAssert(_pdfBase == NULL || pdf == NULL); if (_pdfBase) _pdfBase->Release(); if (pdf) { olChk(pdf->CopyTimesFrom(this)); olChk(pdf->SetClass(_clsid)); olChk(pdf->SetStateBits(_grfStateBits, 0xffffffff)); } _pdfBase = P_TO_BP(CBasedDocFilePtr, pdf); olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::SetBase\n")); // Fall through
EH_Err: return sc; }
//+--------------------------------------------------------------
//
// Member: CWrappedDocFile::CopySelf, public
//
// Synopsis: Duplicates this object
//
// Arguments: [ptsm] - New object return
//
// Returns: Appropriate status code
//
// Modifies: [*pstm] holds pointer to new object if successful
//
// History: 06-Jan-92 DrewB Created
//
//---------------------------------------------------------------
#ifdef INDINST
SCODE CWrappedDocFile::CopySelf(PTSetMember **pptsm) { CDocFile *pdfCopy; SCODE sc;
olDebugOut((DEB_ITRACE, "In CWrappedDocFile::CopySelf()\n")); olChk(_ppubdf->GetScratchDocFile(&pdfCopy)); olChkTo(EH_pdfCopy, CopyDocFileToDocFile(this, pdfCopy, TRUE, FALSE, TRUE, NULL)); olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::CopySelf => %p\n", pdfCopy)); *pptsm = pdfCopy; return S_OK;
EH_pdfCopy: pdfCopy->Destroy(); EH_Err: return sc; } #endif
//+--------------------------------------------------------------
//
// Member: CWrappedDocFile::GetCommitInfo, public
//
// Synopsis: Returns space accounting information for commits
//
// Arguments: [pulRet1] - Return for number of new entries
// [pulRet2] - Return for number of deleted entries
//
// Modifies: [pulRet1]
// [pulRet2]
//
// History: 07-Jul-92 DrewB Created
//
//---------------------------------------------------------------
#ifdef LARGE_STREAMS
void CWrappedDocFile::GetCommitInfo(ULONGLONG *pulRet1, ULONGLONG *pulRet2) #else
void CWrappedDocFile::GetCommitInfo(ULONG *pulRet1, ULONG *pulRet2) #endif
{ CUpdate *pud;
olDebugOut((DEB_ITRACE, "In CWrappedDocFile::GetCommitInfo(%p, %p)\n", pulRet1, pulRet2)); *pulRet1 = 0; *pulRet2 = 0; for (pud = _ulChanged.GetHead(); pud; pud = pud->GetNext()) if (pud->IsCreate()) (*pulRet1)++; else if (pud->IsDelete()) (*pulRet2)++; olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::GetCommitInfo => %Lu, %Lu\n", *pulRet1, *pulRet2)); }
|