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.

429 lines
12 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1999-2001 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // CActionList.cpp
  7. //
  8. // Description:
  9. // Contains the definition of the CActionList class.
  10. //
  11. // Maintained By:
  12. // David Potter (DavidP) 14-JUN-2001
  13. // Vij Vasu (Vvasu) 08-MAR-2000
  14. //
  15. //////////////////////////////////////////////////////////////////////////////
  16. //////////////////////////////////////////////////////////////////////////////
  17. // Include Files
  18. //////////////////////////////////////////////////////////////////////////////
  19. // The precompiled header.
  20. #include "Pch.h"
  21. // For the CActionList class
  22. #include "CActionList.h"
  23. //////////////////////////////////////////////////////////////////////////////
  24. //++
  25. //
  26. // CActionList::CActionList
  27. //
  28. // Description:
  29. // Default constructor of the CActionList class
  30. //
  31. // Arguments:
  32. // None.
  33. //
  34. // Return Value:
  35. // None.
  36. //
  37. // Exceptions Thrown:
  38. // Any exceptions thrown by CList::CList()
  39. //
  40. //--
  41. //////////////////////////////////////////////////////////////////////////////
  42. CActionList::CActionList( void )
  43. {
  44. TraceFunc( "" );
  45. SetRollbackPossible( true );
  46. TraceFuncExit();
  47. } //*** CActionList::CActionList
  48. //////////////////////////////////////////////////////////////////////////////
  49. //++
  50. //
  51. // CActionList::~CActionList
  52. //
  53. // Description:
  54. // Default destructor of the CActionList class. Deletes all the pointers
  55. // in the list.
  56. //
  57. // Arguments:
  58. // None.
  59. //
  60. // Return Value:
  61. // None.
  62. //
  63. // Exceptions Thrown:
  64. // Any exceptions thrown by CList::CList()
  65. //
  66. //--
  67. //////////////////////////////////////////////////////////////////////////////
  68. CActionList::~CActionList( void )
  69. {
  70. TraceFunc( "" );
  71. ActionPtrList::CIterator apliFirst = m_aplPendingActions.CiBegin();
  72. ActionPtrList::CIterator apliCurrent = m_aplPendingActions.CiEnd();
  73. while ( apliCurrent != apliFirst )
  74. {
  75. --apliCurrent;
  76. // Delete this action.
  77. delete (*apliCurrent);
  78. }
  79. TraceFuncExit();
  80. } //*** CActionList::~CActionList
  81. //////////////////////////////////////////////////////////////////////////////
  82. //++
  83. //
  84. // CActionList::Commit
  85. //
  86. // Description:
  87. // Commit this action list. This method iterates through the list
  88. // sequentially and commits each action in the list in turn.
  89. //
  90. // If the commits of any of the actions throws an exeption, then all the
  91. // previously committed actions are rolled back. This exception is then
  92. // thrown back up.
  93. //
  94. // Arguments:
  95. // None.
  96. //
  97. // Return Value:
  98. // None.
  99. //
  100. // Exceptions Thrown:
  101. // Any that are thrown by the contained actions.
  102. //
  103. //--
  104. //////////////////////////////////////////////////////////////////////////////
  105. void
  106. CActionList::Commit( void )
  107. {
  108. TraceFunc( "" );
  109. // Iterator positioned at the first uncommitted action just past the last committed action.
  110. ActionPtrList::CIterator apliFirstUncommitted = m_aplPendingActions.CiBegin();
  111. // Call the base class commit method.
  112. BaseClass::Commit();
  113. try
  114. {
  115. // Walk the list of pending actions and commit them.
  116. CommitList( apliFirstUncommitted );
  117. } // try:
  118. catch( ... )
  119. {
  120. // If we are here, then something went wrong with one of the actions.
  121. LogMsg( "[BC] Caught an exception during commit. The performed actions will be rolled back." );
  122. //
  123. // Rollback all committed actions in the reverse order. apliFirstUncommitted
  124. // is at the first uncommitted action.
  125. // Catch any exceptions thrown during rollback to make sure that there
  126. // is no collided unwind.
  127. //
  128. try
  129. {
  130. RollbackCommitted( apliFirstUncommitted );
  131. }
  132. catch( ... )
  133. {
  134. //
  135. // The rollback of the committed actions has failed.
  136. // There is nothing that we can do, is there?
  137. // We certainly cannot rethrow this exception, since
  138. // the exception that caused the rollback is more important.
  139. //
  140. HRESULT_FROM_WIN32( TW32( ERROR_CLUSCFG_ROLLBACK_FAILED ) );
  141. LogMsg( "[BC] THIS COMPUTER MAY BE IN AN INVALID STATE. Caught an exception during rollback. Rollback will be aborted." );
  142. } // catch: all
  143. // Rethrow the exception thrown by commit.
  144. throw;
  145. } // catch: all
  146. // If we are here, then everything went well.
  147. SetCommitCompleted();
  148. TraceFuncExit();
  149. } //*** CActionList::Commit
  150. //////////////////////////////////////////////////////////////////////////////
  151. //++
  152. //
  153. // CActionList::Rollback
  154. //
  155. // Description:
  156. // Rollback this action list. If this list was successfully committed, then
  157. // this method iterates through the list in the reverse order and rolls
  158. // back action in turn.
  159. //
  160. // Arguments:
  161. // None.
  162. //
  163. // Return Value:
  164. // None.
  165. //
  166. // Exceptions Thrown:
  167. // Any that are thrown by the contained actions.
  168. //
  169. //--
  170. //////////////////////////////////////////////////////////////////////////////
  171. void
  172. CActionList::Rollback( void )
  173. {
  174. TraceFunc( "[IUnknown]" );
  175. // Call the base class rollback method.
  176. BaseClass::Rollback();
  177. LogMsg( "[BC] Attempting to rollback action list." );
  178. // Rollback all actions starting from the last one.
  179. RollbackCommitted( m_aplPendingActions.CiEnd() );
  180. SetCommitCompleted( false );
  181. TraceFuncExit();
  182. } //*** CActionList::Rollback
  183. //////////////////////////////////////////////////////////////////////////////
  184. //++
  185. //
  186. // CActionList::AppendAction
  187. //
  188. // Description:
  189. // Add an action to the end of the list of actions to be performed.
  190. //
  191. // Arguments:
  192. // paNewActionIn
  193. // Pointer to the action that is to be added to the end of the
  194. // action list. This pointer cannot be NULL. The object pointed to by
  195. // this pointer is deleted when this list is deleted.
  196. //
  197. // Return Value:
  198. // None.
  199. //
  200. // Exceptions Thrown:
  201. // CAssert
  202. // If paNewActionIn is NULL.
  203. //
  204. // Any that are thrown by the underlying list.
  205. //
  206. //--
  207. //////////////////////////////////////////////////////////////////////////////
  208. void
  209. CActionList::AppendAction( CAction * paNewActionIn )
  210. {
  211. TraceFunc( "" );
  212. // Temporarily assign pointer to smart pointer to make sure that it is
  213. // deleted if it is not added to the list.
  214. CSmartGenericPtr< CPtrTrait< CAction > > sapTempSmartPtr( paNewActionIn );
  215. if ( paNewActionIn == NULL )
  216. {
  217. LogMsg( "[BC] Cannot append NULL action pointer to list. Throwing an exception." );
  218. THROW_ASSERT(
  219. E_INVALIDARG
  220. , "CActionList::AppendAction() => Cannot append NULL action pointer to list"
  221. );
  222. } // if: the pointer to the action to be appended is NULL
  223. //
  224. LogMsg( "[BC] Appending action (paNewActionIn = %p) to list.", paNewActionIn );
  225. // Add action to the end of the list.
  226. m_aplPendingActions.Append( paNewActionIn );
  227. // The pointer has been added to the list. Give up ownership of the memory.
  228. sapTempSmartPtr.PRelease();
  229. // The rollback capability of the list is the AND of the corresponding property of its member actions.
  230. SetRollbackPossible( FIsRollbackPossible() && paNewActionIn->FIsRollbackPossible() );
  231. // Since a new action has been added, set commit completed to false.
  232. SetCommitCompleted( false );
  233. TraceFuncExit();
  234. } //*** CActionList::AppendAction
  235. //////////////////////////////////////////////////////////////////////////////
  236. //++
  237. //
  238. // CActionList::CommitList
  239. //
  240. // Description:
  241. // Commit the action list of this object. This function is called by
  242. // commit to avoid having loops in a try block.
  243. //
  244. // Arguments:
  245. // rapliFirstUncommittedOut
  246. // An iterator that points to the first uncommitted action.
  247. //
  248. // Return Value:
  249. // None.
  250. //
  251. // Exceptions Thrown:
  252. // Any that are thrown by the contained actions.
  253. //
  254. //--
  255. //////////////////////////////////////////////////////////////////////////////
  256. void
  257. CActionList::CommitList( ActionPtrList::CIterator & rapliFirstUncommittedOut )
  258. {
  259. TraceFunc( "" );
  260. ActionPtrList::CIterator apliCurrent = m_aplPendingActions.CiBegin();
  261. ActionPtrList::CIterator apliLast = m_aplPendingActions.CiEnd();
  262. rapliFirstUncommittedOut = apliCurrent;
  263. while( apliCurrent != apliLast )
  264. {
  265. LogMsg( "[BC] About to commit action (pointer = %#p)", *apliCurrent );
  266. // Commit the current action.
  267. (*apliCurrent)->Commit();
  268. // Move to the next action.
  269. ++apliCurrent;
  270. // This is now the first uncommitted action.
  271. rapliFirstUncommittedOut = apliCurrent;
  272. } // while: there still are actions to be committed.
  273. TraceFuncExit();
  274. } //*** CActionList::CommitList
  275. //////////////////////////////////////////////////////////////////////////////
  276. //++
  277. //
  278. // CActionList::RollbackCommitted
  279. //
  280. // Description:
  281. // Rollback all actions that have been committed.
  282. //
  283. // Arguments:
  284. // rapliFirstUncommittedIn
  285. // An iterator that points to the first uncommitted action.
  286. //
  287. // Return Value:
  288. // None.
  289. //
  290. // Exceptions Thrown:
  291. // Any that are thrown by the contained actions.
  292. //
  293. //--
  294. //////////////////////////////////////////////////////////////////////////////
  295. void
  296. CActionList::RollbackCommitted( const ActionPtrList::CIterator & rapliFirstUncommittedIn )
  297. {
  298. TraceFunc( "" );
  299. ActionPtrList::CIterator apliFirst = m_aplPendingActions.CiBegin();
  300. ActionPtrList::CIterator apliCurrent = rapliFirstUncommittedIn;
  301. while ( apliCurrent != apliFirst )
  302. {
  303. --apliCurrent;
  304. // apliCurrent is now at the last committed action.
  305. LogMsg( "[BC] About to rollback action (pointer = %#p)", *apliCurrent );
  306. // Rollback the last un-rolledback, committed action.
  307. if ( (*apliCurrent)->FIsRollbackPossible() )
  308. {
  309. (*apliCurrent)->Rollback();
  310. } // if: this action can be rolled back
  311. else
  312. {
  313. LogMsg( "[BC] THIS COMPUTER MAY BE IN AN INVALID STATE. Action cannot be rolled back. Rollback was aborted." );
  314. } // else: this action cannot be rolled back
  315. } // while: more actions
  316. TraceFuncExit();
  317. } //*** CActionList::RollbackCommitted
  318. //////////////////////////////////////////////////////////////////////////////
  319. //++
  320. //
  321. // CActionList::UiGetMaxProgressTicks
  322. //
  323. // Description:
  324. // Returns the number of progress messages that this action will send.
  325. //
  326. // Arguments:
  327. // None.
  328. //
  329. // Return Value:
  330. // None.
  331. //
  332. // Exceptions Thrown:
  333. // None.
  334. //
  335. //--
  336. //////////////////////////////////////////////////////////////////////////////
  337. UINT
  338. CActionList::UiGetMaxProgressTicks( void ) const throw()
  339. {
  340. TraceFunc( "" );
  341. UINT uiRetVal = 0;
  342. ActionPtrList::CIterator apliCurrent = m_aplPendingActions.CiBegin();
  343. ActionPtrList::CIterator apliLast = m_aplPendingActions.CiEnd();
  344. while ( apliCurrent != apliLast )
  345. {
  346. uiRetVal += (*apliCurrent)->UiGetMaxProgressTicks();
  347. ++apliCurrent;
  348. }
  349. RETURN( uiRetVal );
  350. } //*** CActionList::UiGetMaxProgressTicks