Leaked source code of windows server 2003
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.

567 lines
18 KiB

  1. //+--------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1992.
  5. //
  6. // File: wdfxact.cxx
  7. //
  8. // Contents: CWrappedDocFile transactioning methods
  9. //
  10. // History: 22-Jan-92 DrewB Created
  11. //
  12. //---------------------------------------------------------------
  13. #include <dfhead.cxx>
  14. #pragma hdrstop
  15. #include <sstream.hxx>
  16. #include <tstream.hxx>
  17. #include <dfdeb.hxx>
  18. //+--------------------------------------------------------------
  19. //
  20. // Member: CWrappedDocFile::BeginCommit, public
  21. //
  22. // Synopsis: Allocates commit resources for two-phase commit
  23. //
  24. // Arguments: [dwFlags] - Flags
  25. //
  26. // Returns: Appropriate status code
  27. //
  28. // History: 06-Jan-92 DrewB Created
  29. //
  30. //---------------------------------------------------------------
  31. SCODE CWrappedDocFile::BeginCommit(DWORD const dwFlags)
  32. {
  33. SCODE sc;
  34. #ifdef INDINST
  35. DFSIGNATURE sigNew;
  36. #endif
  37. olDebugOut((DEB_ITRACE, "In CWrappedDocFile::BeginCommit(%lX)\n",
  38. dwFlags));
  39. olAssert(_pdfBase != NULL);
  40. olAssert(P_TRANSACTED(_df));
  41. #if DBG == 1
  42. if (!HaveResource(DBR_XSCOMMITS, 1))
  43. olErr(EH_Err, STG_E_ABNORMALAPIEXIT);
  44. #endif
  45. _fBeginCommit = TRUE;
  46. #ifdef INDINST
  47. _ppubdf->GetNewSignature(&sigNew);
  48. olChk(_pdfBase->BeginCommitFromChild(_ulChanged, NULL,
  49. _sigBase, sigNew, dwFlags, _ppubdf));
  50. // INDINST - Ownership of dirty and changed?
  51. if (P_INDEPENDENT(_df) && _pdfParent)
  52. olChkTo(EH_Begin,
  53. _pdfParent->BeginCommitFromChild(_ulChanged,
  54. _pdfBase, _sigBase, sigNew,
  55. dwFlags, _ppubdf));
  56. _sigBaseOld = _sigBase;
  57. _sigCombinedOld = _sigCombined;
  58. _sigBase = _sigCombined = sigNew;
  59. #else
  60. olChk(_pdfBase->BeginCommitFromChild(_ulChanged, dwFlags, this));
  61. #endif
  62. olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::BeginCommit\n"));
  63. return S_OK;
  64. #ifdef INDINST
  65. EH_Begin:
  66. _pdfBase->EndCommitFromChild(DF_ABORT);
  67. #endif
  68. EH_Err:
  69. return sc;
  70. }
  71. //+--------------------------------------------------------------
  72. //
  73. // Member: CWrappedDocFile::EndCommit, public
  74. //
  75. // Synopsis: Performs actual commit/abort for two-phase commit
  76. //
  77. // Arguments: [df] - COMMIT/ABORT
  78. //
  79. // Returns: Appropriate status code
  80. //
  81. // History: 06-Jan-92 DrewB Created
  82. //
  83. //---------------------------------------------------------------
  84. void CWrappedDocFile::EndCommit(DFLAGS const df)
  85. {
  86. olDebugOut((DEB_ITRACE, "In CWrappedDocFile::EndCommit(%X)\n",
  87. df));
  88. olAssert(P_TRANSACTED(_df));
  89. if (!_fBeginCommit)
  90. return;
  91. _fBeginCommit = FALSE;
  92. #if DBG == 1
  93. if (P_COMMIT(df))
  94. ModifyResLimit(DBR_XSCOMMITS, 1);
  95. #endif
  96. _pdfBase->EndCommitFromChild(df, this);
  97. #ifdef INDINST
  98. if (P_INDEPENDENT(_df) && _pdfParent)
  99. olVerSucc(_pdfParent->EndCommitFromChild(df));
  100. #endif
  101. if (P_COMMIT(df))
  102. {
  103. // These are nulled because the memory should be gone
  104. _ulChanged.Unlink();
  105. SetClean();
  106. }
  107. else
  108. {
  109. #ifdef INDINST
  110. _sigBase = _sigBaseOld;
  111. _sigCombined = _sigCombinedOld;
  112. #endif
  113. }
  114. olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::EndCommit\n"));
  115. }
  116. //+--------------------------------------------------------------
  117. //
  118. // Member: CWrappedDocFile::Revert, public
  119. //
  120. // Synopsis: Transaction level has requested revert
  121. //
  122. // History: 06-Jan-92 DrewB Created
  123. //
  124. //---------------------------------------------------------------
  125. void CWrappedDocFile::Revert(void)
  126. {
  127. CUpdate *pud;
  128. olDebugOut((DEB_ITRACE, "In CWrappedDocFile %p::Revert()\n", this));
  129. for (pud = _ulChanged.GetTail(); pud; pud = pud->GetPrev())
  130. RevertUpdate(pud);
  131. _ulChanged.Empty();
  132. olVerSucc(SetInitialState(BP_TO_P(PDocFile *, _pdfBase)));
  133. SetClean();
  134. olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::Revert\n"));
  135. }
  136. //+--------------------------------------------------------------
  137. //
  138. // Member: CWrappedDocFile::BeginCommitFromChild, public
  139. //
  140. // Synopsis: Start two-phase commit, requested by child
  141. //
  142. // Arguments: [ulChanged] - Change list
  143. // [dwFlags] - Flags controlling commit
  144. // [pdfChild] - Child object
  145. //
  146. // Returns: Appropriate status code
  147. //
  148. // History: 06-Jan-92 DrewB Created
  149. //
  150. //---------------------------------------------------------------
  151. SCODE CWrappedDocFile::BeginCommitFromChild(CUpdateList &ulChanged,
  152. DWORD const dwFlags,
  153. CWrappedDocFile *pdfChild)
  154. {
  155. CUpdate *pud, *pudNext;
  156. olDebugOut((DEB_ITRACE, "In CWrappedDocFile::BeginCommitFromChild:%p("
  157. "%p, %lX, %p)\n", this, ulChanged.GetHead(), dwFlags,
  158. pdfChild));
  159. UNREFERENCED_PARM(pdfChild);
  160. olAssert(P_TRANSACTED(_df));
  161. olAssert(_tssDeletedHolder.GetHead() == NULL);
  162. _ulChangedHolder = ulChanged;
  163. _ulChangedOld = _ulChanged;
  164. for (pud = ulChanged.GetHead(); pud; pud = pudNext)
  165. {
  166. if (pud->IsRename())
  167. _ppubdf->RenameChild(pud->GetOriginalName(), GetName(),
  168. pud->GetCurrentName());
  169. else if (pud->IsDelete())
  170. {
  171. PTSetMember *ptsm;
  172. if ((ptsm = _ppubdf->FindXSMember(pud->GetOriginalName(),
  173. GetName())) != NULL)
  174. {
  175. olAssert(ptsm->GetName() != DF_NOLUID &&
  176. aMsg("Can't destroy NOLUID XSM"));
  177. // Take a reference because RemoveXSMember
  178. // will call Release
  179. ptsm->AddRef();
  180. _ppubdf->RemoveXSMember(ptsm);
  181. _tssDeletedHolder.AddMember(ptsm);
  182. }
  183. }
  184. else
  185. if (pud->IsCreate())
  186. olVerSucc(CreateFromUpdate(pud, this,
  187. DF_WRITE | DF_NOUPDATE |
  188. DF_TRANSACTED));
  189. pudNext = pud->GetNext();
  190. _ulChanged.Append(pud);
  191. }
  192. olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::BeginCommitFromChild\n"));
  193. return S_OK;
  194. }
  195. //+--------------------------------------------------------------
  196. //
  197. // Member: CWrappedDocFile::EndCommitFromChild
  198. //
  199. // Synopsis: Ends two-phase commit, requested by child
  200. //
  201. // Arguments: [df] - COMMIT/ABORT
  202. // [pdfChild] - Child object
  203. //
  204. // Returns: Appropriate status code
  205. //
  206. // History: 06-Jan-92 DrewB Created
  207. //
  208. //---------------------------------------------------------------
  209. void CWrappedDocFile::EndCommitFromChild(DFLAGS const df,
  210. CWrappedDocFile *pdfChild)
  211. {
  212. PTSetMember *ptsm;
  213. CUpdate *pud;
  214. olDebugOut((DEB_ITRACE, "In CWrappedDocFile::EndCommitFromChild:%p("
  215. "%X, %p)\n", this, df, pdfChild));
  216. olAssert(P_TRANSACTED(_df));
  217. if (!P_COMMIT(df))
  218. {
  219. // Restore our update list
  220. _ulChanged = _ulChangedOld;
  221. // Unconcat _ulChanged and ulChanged
  222. if (_ulChanged.GetTail())
  223. _ulChanged.GetTail()->SetNext(NULL);
  224. if (_ulChangedHolder.GetHead())
  225. _ulChangedHolder.GetHead()->SetPrev(NULL);
  226. // Back out updates
  227. for (pud = _ulChangedHolder.GetTail(); pud; pud = pud->GetPrev())
  228. if (pud->IsCreate())
  229. {
  230. // We need to do two things:
  231. //
  232. // Break any SetBase links that might have been created
  233. //
  234. // Return newly created objects to the creators so
  235. // that they can be returned to the preallocation
  236. // pool
  237. if ((pud->GetFlags() & (ULF_TYPEFLAGS & STGTY_REAL)) ==
  238. STGTY_STORAGE)
  239. {
  240. CWrappedDocFile *pwdf = (CWrappedDocFile *)pud->GetXSM();
  241. CWrappedDocFile *pwdfBase;
  242. if (pwdf != NULL &&
  243. (pwdfBase = (CWrappedDocFile *)pwdf->GetBase()) !=
  244. NULL)
  245. {
  246. // Increase ref count because SetBase will release
  247. pwdfBase->AddRef();
  248. pwdf->SetBase(NULL);
  249. ReturnDocFile(pwdfBase);
  250. }
  251. }
  252. else
  253. {
  254. CTransactedStream *ptstm = (CTransactedStream *)pud->
  255. GetXSM();
  256. CTransactedStream *ptstmBase;
  257. olAssert((pud->GetFlags() & (ULF_TYPEFLAGS & STGTY_REAL))
  258. == STGTY_STREAM);
  259. if (ptstm != NULL &&
  260. (ptstmBase = (CTransactedStream *)ptstm->GetBase()) !=
  261. NULL)
  262. {
  263. // Increase ref count because SetBase will release
  264. ptstmBase->AddRef();
  265. ptstm->SetBase(NULL);
  266. ReturnStream(ptstmBase);
  267. }
  268. }
  269. }
  270. else if (pud->IsDelete())
  271. {
  272. // We use GetName() as the tree because we know that
  273. // only immediate children can show up in delete records
  274. if ((ptsm = _tssDeletedHolder.FindName(pud->GetOriginalName(),
  275. GetName())) != NULL)
  276. {
  277. _tssDeletedHolder.RemoveMember(ptsm);
  278. _ppubdf->InsertXSMember(ptsm);
  279. // Release the reference we took in BeginCommitFromChild
  280. // because InsertXSMember takes a reference
  281. ptsm->Release();
  282. }
  283. }
  284. else if (pud->IsRename())
  285. {
  286. // Roll back renames
  287. olAssert(_ppubdf->FindXSMember(pud->GetOriginalName(),
  288. GetName()) == NULL &&
  289. aMsg("Abort commit rename precondition"));
  290. _ppubdf->RenameChild(pud->GetCurrentName(), GetName(),
  291. pud->GetOriginalName());
  292. olAssert(_ppubdf->FindXSMember(pud->GetCurrentName(),
  293. GetName()) == NULL &&
  294. aMsg("Abort commit rename postcondition"));
  295. }
  296. }
  297. else
  298. {
  299. // Finalize creations
  300. for (pud = _ulChangedHolder.GetHead(); pud; pud = pud->GetNext())
  301. if (pud->IsCreate())
  302. {
  303. // Since the object pointed to by GetBase is at our level,
  304. // we know it is transacted so we can safely cast to
  305. // PTSetMember
  306. if ((pud->GetFlags() & (ULF_TYPEFLAGS & STGTY_REAL)) ==
  307. STGTY_STORAGE)
  308. {
  309. ptsm = (CWrappedDocFile *)
  310. ((CWrappedDocFile *)pud->GetXSM())->GetBase();
  311. }
  312. else
  313. {
  314. olAssert((pud->GetFlags() & (ULF_TYPEFLAGS & STGTY_REAL))
  315. == STGTY_STREAM);
  316. ptsm = (CTransactedStream *)
  317. ((CTransactedStream *)pud->GetXSM())->GetBase();
  318. }
  319. pud->SetXSM(ptsm);
  320. }
  321. // Finalize deletions
  322. while (ptsm = _tssDeletedHolder.GetHead())
  323. {
  324. olAssert(ptsm->GetName() != DF_NOLUID &&
  325. aMsg("Can't destroy NOLUID XSM"));
  326. _ppubdf->DestroyChild(ptsm->GetName());
  327. _tssDeletedHolder.RemoveMember(ptsm);
  328. ptsm->Release();
  329. }
  330. // Pick up state information
  331. TIME_T tm;
  332. if (pdfChild->GetDirty() & DIRTY_CREATETIME)
  333. {
  334. olVerSucc(pdfChild->GetTime(WT_CREATION, &tm));
  335. olVerSucc(SetTime(WT_CREATION, tm));
  336. }
  337. if (pdfChild->GetDirty() & DIRTY_MODIFYTIME)
  338. {
  339. olVerSucc(pdfChild->GetTime(WT_MODIFICATION, &tm));
  340. olVerSucc(SetTime(WT_MODIFICATION, tm));
  341. }
  342. if (pdfChild->GetDirty() & DIRTY_ACCESSTIME)
  343. {
  344. olVerSucc(pdfChild->GetTime(WT_ACCESS, &tm));
  345. olVerSucc(SetTime(WT_ACCESS, tm));
  346. }
  347. if (pdfChild->GetDirty() & DIRTY_CLASS)
  348. {
  349. CLSID cls;
  350. olVerSucc(pdfChild->GetClass(&cls));
  351. olVerSucc(SetClass(cls));
  352. }
  353. if (pdfChild->GetDirty() & DIRTY_STATEBITS)
  354. {
  355. DWORD dwState;
  356. olVerSucc(pdfChild->GetStateBits(&dwState));
  357. olVerSucc(SetStateBits(dwState, 0xffffffff));
  358. }
  359. }
  360. // Forget temporary commit lists
  361. _ulChangedOld.Unlink();
  362. _ulChangedHolder.Unlink();
  363. olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::EndCommitFromChild\n"));
  364. }
  365. //+--------------------------------------------------------------
  366. //
  367. // Member: CWrappedDocFile::GetSignature, public
  368. //
  369. // Synopsis: Returns signature
  370. //
  371. // Returns: Appropriate status code
  372. //
  373. // History: 06-Jan-92 DrewB Created
  374. //
  375. //---------------------------------------------------------------
  376. #ifdef INDINST
  377. void CWrappedDocFile::GetSignature(DFSIGNATURE *psig)
  378. {
  379. olDebugOut((DEB_ITRACE, "In CWrappedDocFile::GetSignature()\n"));
  380. olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::GetSignature => %ld\n",
  381. _sigCombined));
  382. *psig = _sigCombined;
  383. }
  384. #endif
  385. //+--------------------------------------------------------------
  386. //
  387. // Member: CWrappedDocFile::SetSignature, public
  388. //
  389. // Synopsis: Sets the signature
  390. //
  391. // Arguments: [sig] - Signature
  392. //
  393. // Returns: Appropriate status code
  394. //
  395. // History: 04-Feb-92 DrewB Created
  396. //
  397. //---------------------------------------------------------------
  398. #ifdef INDINST
  399. void CWrappedDocFile::SetSignature(DFSIGNATURE sig)
  400. {
  401. olDebugOut((DEB_ITRACE, "In CWrappedDocFile::SetSignature(%ld)\n", sig));
  402. _sigCombined = sig;
  403. olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::SetSignature\n"));
  404. }
  405. #endif
  406. //+--------------------------------------------------------------
  407. //
  408. // Member: CWrappedDocFile::SetBase, public
  409. //
  410. // Synopsis: Sets Base pointer
  411. //
  412. // Arguments: [pdf] - New base
  413. //
  414. // Returns: Appropriate status code
  415. //
  416. // History: 06-Jan-92 DrewB Created
  417. //
  418. //---------------------------------------------------------------
  419. SCODE CWrappedDocFile::SetBase(PDocFile *pdf)
  420. {
  421. SCODE sc = S_OK;
  422. olDebugOut((DEB_ITRACE, "In CWrappedDocFile::SetBase(%p)\n", pdf));
  423. olAssert(_pdfBase == NULL || pdf == NULL);
  424. if (_pdfBase)
  425. _pdfBase->Release();
  426. if (pdf)
  427. {
  428. olChk(pdf->CopyTimesFrom(this));
  429. olChk(pdf->SetClass(_clsid));
  430. olChk(pdf->SetStateBits(_grfStateBits, 0xffffffff));
  431. }
  432. _pdfBase = P_TO_BP(CBasedDocFilePtr, pdf);
  433. olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::SetBase\n"));
  434. // Fall through
  435. EH_Err:
  436. return sc;
  437. }
  438. //+--------------------------------------------------------------
  439. //
  440. // Member: CWrappedDocFile::CopySelf, public
  441. //
  442. // Synopsis: Duplicates this object
  443. //
  444. // Arguments: [ptsm] - New object return
  445. //
  446. // Returns: Appropriate status code
  447. //
  448. // Modifies: [*pstm] holds pointer to new object if successful
  449. //
  450. // History: 06-Jan-92 DrewB Created
  451. //
  452. //---------------------------------------------------------------
  453. #ifdef INDINST
  454. SCODE CWrappedDocFile::CopySelf(PTSetMember **pptsm)
  455. {
  456. CDocFile *pdfCopy;
  457. SCODE sc;
  458. olDebugOut((DEB_ITRACE, "In CWrappedDocFile::CopySelf()\n"));
  459. olChk(_ppubdf->GetScratchDocFile(&pdfCopy));
  460. olChkTo(EH_pdfCopy,
  461. CopyDocFileToDocFile(this, pdfCopy, TRUE, FALSE, TRUE, NULL));
  462. olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::CopySelf => %p\n",
  463. pdfCopy));
  464. *pptsm = pdfCopy;
  465. return S_OK;
  466. EH_pdfCopy:
  467. pdfCopy->Destroy();
  468. EH_Err:
  469. return sc;
  470. }
  471. #endif
  472. //+--------------------------------------------------------------
  473. //
  474. // Member: CWrappedDocFile::GetCommitInfo, public
  475. //
  476. // Synopsis: Returns space accounting information for commits
  477. //
  478. // Arguments: [pulRet1] - Return for number of new entries
  479. // [pulRet2] - Return for number of deleted entries
  480. //
  481. // Modifies: [pulRet1]
  482. // [pulRet2]
  483. //
  484. // History: 07-Jul-92 DrewB Created
  485. //
  486. //---------------------------------------------------------------
  487. #ifdef LARGE_STREAMS
  488. void CWrappedDocFile::GetCommitInfo(ULONGLONG *pulRet1, ULONGLONG *pulRet2)
  489. #else
  490. void CWrappedDocFile::GetCommitInfo(ULONG *pulRet1, ULONG *pulRet2)
  491. #endif
  492. {
  493. CUpdate *pud;
  494. olDebugOut((DEB_ITRACE, "In CWrappedDocFile::GetCommitInfo(%p, %p)\n",
  495. pulRet1, pulRet2));
  496. *pulRet1 = 0;
  497. *pulRet2 = 0;
  498. for (pud = _ulChanged.GetHead(); pud; pud = pud->GetNext())
  499. if (pud->IsCreate())
  500. (*pulRet1)++;
  501. else if (pud->IsDelete())
  502. (*pulRet2)++;
  503. olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::GetCommitInfo => %Lu, %Lu\n",
  504. *pulRet1, *pulRet2));
  505. }