Source code of Windows XP (NT5)
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.

532 lines
16 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991 - 1998.
  5. //
  6. // File: FRESH.CXX
  7. //
  8. // Contents: Fresh list
  9. //
  10. // Classes: CFresh
  11. //
  12. // History: 16-May-91 BartoszM Created.
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.cxx>
  16. #pragma hdrstop
  17. #include <enumstr.hxx>
  18. #include "fresh.hxx"
  19. #include "fretest.hxx"
  20. #include "indxact.hxx"
  21. #include "merge.hxx"
  22. #include "wordlist.hxx"
  23. class CEnumWorkid;
  24. //+---------------------------------------------------------------------------
  25. //
  26. // Member: CFresh::CFresh, public
  27. //
  28. // Synopsis: Constructor.
  29. //
  30. // History: 16-May-91 BartoszM Created.
  31. //
  32. //----------------------------------------------------------------------------
  33. CFresh::CFresh ( PStorage& storage, CTransaction& xact, CPartList & partList )
  34. : _storage( storage ),
  35. _persFresh( storage, partList ),
  36. _master( 0 ),
  37. _partList( partList )
  38. {
  39. ULONG count = max( _persFresh.GetPersRecCount(), 100 );
  40. XPtr<CFreshTest> xMaster( new CFreshTest ( count ) );
  41. SFreshTable freshTable( xMaster.GetReference() );
  42. _persFresh.LoadFreshTest( *freshTable );
  43. _master = xMaster.Acquire();
  44. }
  45. //+---------------------------------------------------------------------------
  46. //
  47. // Member: CFresh::~CFresh, public
  48. //
  49. // Synopsis: Destructor.
  50. //
  51. // History: 16-May-91 BartoszM Created.
  52. //
  53. //----------------------------------------------------------------------------
  54. CFresh::~CFresh ()
  55. {
  56. delete _master;
  57. }
  58. //+---------------------------------------------------------------------------
  59. //
  60. // Member: CFresh::LokInit, public
  61. //
  62. // Synopsis: Empties and re-initializes the fresh test
  63. //
  64. // History: 15-Nov-94 DwightKr Created.
  65. //
  66. //----------------------------------------------------------------------------
  67. void CFresh::LokInit()
  68. {
  69. _persFresh.LokEmpty();
  70. unsigned count = 100;
  71. CFreshTest* newFreshTest = new CFreshTest ( count );
  72. LokCommitMaster( newFreshTest );
  73. }
  74. //+---------------------------------------------------------------------------
  75. //
  76. // Member: CFresh::LokGetFreshTest, public
  77. //
  78. // Synopsis: Creates CFreshTest object
  79. //
  80. // History: 16-May-91 BartoszM Created.
  81. //
  82. // Notes: ResMan LOCKED
  83. // FreshTest has to be released
  84. //
  85. //----------------------------------------------------------------------------
  86. CFreshTest* CFresh::LokGetFreshTest()
  87. {
  88. ciDebugOut (( DEB_ITRACE, ">> get fresh test\n"));
  89. _master->Reference();
  90. return _master;
  91. }
  92. //+---------------------------------------------------------------------------
  93. //
  94. // Member: CFresh::LokReleaseFreshTest, public
  95. //
  96. // Synopsis: Dereferences CFreshTest object
  97. //
  98. // History: 16-May-91 BartoszM Created.
  99. //
  100. // Notes: ResMan LOCKED
  101. //
  102. //----------------------------------------------------------------------------
  103. void CFresh::LokReleaseFreshTest( CFreshTest* test )
  104. {
  105. ciDebugOut (( DEB_ITRACE, "<< release fresh test\n" ));
  106. if ( test != 0 && test->Dereference() == 0 && test != _master )
  107. {
  108. delete test;
  109. }
  110. }
  111. //+---------------------------------------------------------------------------
  112. //
  113. // Member: CFresh::LokCommitMaster, public
  114. //
  115. // Synopsis: Adds a new master fresh test
  116. //
  117. // History: 16-May-91 BartoszM Created.
  118. //
  119. // Notes: ResMan LOCKED
  120. //
  121. //----------------------------------------------------------------------------
  122. void CFresh::LokCommitMaster ( CFreshTest* newMaster )
  123. {
  124. ciDebugOut (( DEB_ITRACE, "Commit new master fresh test\n" ));
  125. Win4Assert ( newMaster != 0 );
  126. Win4Assert ( _master != 0 );
  127. CFreshTest* old = _master;
  128. _master = newMaster;
  129. ciDebugOut(( DEB_ITRACE, "New master (0x%x) has %u deletes\n", _master, _master->DeleteCount() ));
  130. if ( !old->InUse() )
  131. {
  132. delete old;
  133. }
  134. }
  135. //+---------------------------------------------------------------------------
  136. //
  137. // Member: CFresh::LokAddIndex, public
  138. //
  139. // Synopsis: Adds new mapping iid <-> documents after filtering
  140. //
  141. // Arguments: [xact] -- transaction
  142. // [iid] -- index id
  143. // [iidDeleted] -- index id for deleted objects
  144. // [docList] -- list of wids
  145. //
  146. // History: 16-May-91 BartoszM Created.
  147. //
  148. // Notes: ResMan LOCKED
  149. //
  150. //----------------------------------------------------------------------------
  151. void CFresh::LokAddIndex ( CIndexTrans& xact,
  152. INDEXID iid, INDEXID iidDeleted,
  153. CDocList& docList, CWordList const & wordList )
  154. {
  155. ciDebugOut (( DEB_ITRACE, "Fresh: Adding documents, iid %lx\n", iid ));
  156. CFreshTest* newMaster = new CFreshTest ( *_master );
  157. xact.LogFresh ( newMaster );
  158. unsigned cDocuments = docList.Count();
  159. for ( unsigned i = 0; i < cDocuments; i++ )
  160. {
  161. STATUS status = docList.Status(i);
  162. if ( status == SUCCESS )
  163. {
  164. WORKID wid = docList.Wid(i);
  165. ciDebugOut (( DEB_FRESH, "Fresh wid %ld, iid %lx\n", wid, iid ));
  166. #if CIDBG==1
  167. Win4Assert( widInvalid != wid &&
  168. wordList.IsWorkIdPresent( wid ) );
  169. #endif // CIDBG==1
  170. newMaster->AddReplace ( wid, iid );
  171. }
  172. else if ( status == DELETED || status == WL_NULL )
  173. {
  174. WORKID wid = docList.Wid(i);
  175. ciDebugOut (( DEB_FRESH, "Fresh wid %ld deleted \n", wid ));
  176. newMaster->AddReplaceDelete ( wid, iidDeleted );
  177. }
  178. else
  179. {
  180. ciDebugOut (( DEB_FRESH,
  181. "Fresh wid %ld, not changed. Status 0x%X\n",
  182. docList.Wid(i), status ));
  183. #if CIDBG==1
  184. Win4Assert( !wordList.IsWorkIdPresent( docList.Wid(i)) );
  185. #endif // CIDBG==1
  186. }
  187. }
  188. newMaster->ModificationsComplete();
  189. }
  190. //+---------------------------------------------------------------------------
  191. //
  192. // Member: CFresh::LokDeleteDocuments, public
  193. //
  194. // Synopsis: Mark documents as deleted
  195. //
  196. // Arguments: [xact] -- transaction
  197. // [docList] -- list of wids
  198. // [iidDeleted] -- index id for deleted objects
  199. //
  200. // History: 16-May-91 BartoszM Created.
  201. // 12-Jun-97 KyleP Track unlogged deletions
  202. //
  203. // Notes: ResMan LOCKED
  204. //
  205. //----------------------------------------------------------------------------
  206. void CFresh::LokDeleteDocuments( CIndexTrans& xact,
  207. CDocList& docList,
  208. INDEXID iidDeleted )
  209. {
  210. ciDebugOut (( DEB_ITRACE, "Fresh: Deleting documents\n" ));
  211. CFreshTest* newMaster = new CFreshTest ( *_master );
  212. xact.LogFresh ( newMaster );
  213. unsigned cDocuments = docList.Count();
  214. for ( unsigned i = 0; i < cDocuments; i++ )
  215. {
  216. if ( docList.Status(i) == DELETED)
  217. {
  218. WORKID wid = docList.Wid(i);
  219. ciDebugOut (( DEB_FRESH, "Fresh wid %ld deleted \n", wid ));
  220. newMaster->AddReplaceDelete ( wid, iidDeleted );
  221. }
  222. }
  223. newMaster->ModificationsComplete();
  224. }
  225. //+---------------------------------------------------------------------------
  226. //
  227. // Member: CFresh::LokUpdate, public
  228. //
  229. // Synopsis: Replaces old entries with the more recent entries after merge
  230. //
  231. // Arguments: [merge] -- Merge object
  232. // [xact] -- Merge transaction
  233. // [newFreshLog] -- New fresh log
  234. // [newIid] -- New index id
  235. // [cInd] -- Count of index id's to be replaced
  236. // [aIidOld] -- Array of index id's to be replaced
  237. // [xFreshTestAtMerge] -- If a new fresh test that was used at
  238. // merge time is created, store in here
  239. //
  240. // History: 16-May-91 BartoszM Created.
  241. // 01-Dec-93 DwightKr Write changes to pers. fresh log
  242. // 04-Oct-94 SrikantS Support for creating a new fresh
  243. // log after merge.
  244. //
  245. // Notes: ResMan LOCKED
  246. //
  247. //----------------------------------------------------------------------------
  248. WORKID CFresh::LokUpdate ( CMerge& merge,
  249. CMergeTrans& xact,
  250. CPersFresh & newFreshLog,
  251. INDEXID newIid,
  252. int cInd,
  253. INDEXID aIidOld[],
  254. XPtr<CFreshTest> & xFreshTestAtMerge )
  255. {
  256. ciDebugOut (( DEB_ITRACE, "Fresh list: updating %d entries\n", cInd ));
  257. CIdxSubstitution subst (FALSE, newIid, cInd, aIidOld);
  258. CFreshTest * newMaster = new CFreshTest( *_master, subst );
  259. xact.LogFresh( newMaster );
  260. WORKID widNewFreshLog;
  261. //
  262. // The new memory fresh test is created by applying the transformtion on
  263. // the master fresh test. We should apply the transformation for
  264. // persistent log on the freshtest used by the merge. If a fresh test is
  265. // created then we pass ownership to xFreshTestAtMerge, so that
  266. // LokDeleteWidsInPersistentIndex can use the newly created fresh test.
  267. //
  268. // optimization to avoid creating a new fresh test
  269. if ( _master == merge.GetFresh() )
  270. {
  271. widNewFreshLog = LokBuildNewFreshLog( newMaster, newFreshLog, subst);
  272. newMaster->DecrementDeleteCount( _master->DeleteCount() );
  273. }
  274. else
  275. {
  276. xFreshTestAtMerge.Set( new CFreshTest( *(merge.GetFresh()), subst ) );
  277. widNewFreshLog = LokBuildNewFreshLog( xFreshTestAtMerge.GetPointer(),
  278. newFreshLog,
  279. subst );
  280. newMaster->DecrementDeleteCount( xFreshTestAtMerge->DeleteCount() );
  281. }
  282. newMaster->ModificationsComplete();
  283. xact.LogNewFreshLog( newMaster, widNewFreshLog );
  284. return widNewFreshLog;
  285. }
  286. //+---------------------------------------------------------------------------
  287. //
  288. // Member: CFresh::LokRemoveIndexes, public
  289. //
  290. // Synopsis: Removes indexes from table after master merge
  291. //
  292. // Arguments: [xact] -- merge transaction
  293. // [cInd] -- count of inexes to be removed
  294. // [aIidOld] -- array of index ids of obsolete indexes
  295. // [iidOldDeleted] -- old index id for deleted objects
  296. //
  297. // History: 16-May-91 BartoszM Created.
  298. //
  299. // Notes: ResMan LOCKED
  300. //
  301. //----------------------------------------------------------------------------
  302. WORKID CFresh::LokRemoveIndexes( CMergeTrans& xact,
  303. CPersFresh & newFreshLog,
  304. unsigned cInd,
  305. INDEXID aIidOld[],
  306. INDEXID iidOldDeleted )
  307. {
  308. ciDebugOut (( DEB_ITRACE, "FreshList: Removing indexes\n" ));
  309. CIdxSubstitution subst (TRUE, iidOldDeleted, cInd, aIidOld);
  310. XPtr<CFreshTest> xNewMaster( new CFreshTest( *_master, subst ) );
  311. WORKID widNewFreshLog = LokBuildNewFreshLog( xNewMaster.GetPointer(),
  312. newFreshLog,
  313. subst );
  314. // LogNewFreshLog can't fail, so the acquire is safe to do
  315. // before the call.
  316. xNewMaster->ModificationsComplete();
  317. xact.LogNewFreshLog( xNewMaster.Acquire(), widNewFreshLog );
  318. return(widNewFreshLog);
  319. }
  320. //+---------------------------------------------------------------------------
  321. //
  322. // Function: LokBuildNewFreshLog
  323. //
  324. // Synopsis: Builds a new persistent fresh log by combining the existing
  325. // fresh log and the new fresh test.
  326. //
  327. // Arguments: [newFreTest] -- Input - the new fresh test.
  328. // [newFreshLog] -- Input/Output - the new fresh log object.
  329. // [subst] -- Index substitution object
  330. //
  331. // Returns: ObjectId of the new persistent fresh log created.
  332. //
  333. // History: 03-Oct-94 srikants Created
  334. // 11-Jun-97 KyleP Track unlogged deletions
  335. //
  336. //----------------------------------------------------------------------------
  337. WORKID CFresh::LokBuildNewFreshLog( CFreshTest * newFreTest,
  338. CPersFresh & newFreshLog,
  339. CIdxSubstitution& subst )
  340. {
  341. SFreshTable freshTable( *newFreTest );
  342. CFreshTableIter iter( *freshTable );
  343. //
  344. // Create a new persistent fresh log.
  345. //
  346. WORKID widNewFreshLog = _storage.GetNewObjectIdForFreshLog();
  347. _storage.InitRcovObj( widNewFreshLog, FALSE );
  348. PRcovStorageObj *pPersFreshLog = _storage.QueryFreshLog( widNewFreshLog );
  349. SRcovStorageObj PersFreshLog( pPersFreshLog );
  350. //
  351. // Inside kernel, we are guaranteed that a new object has no data in
  352. // it. In user space, we may be using an object that was not deleted
  353. // before due to a failure.
  354. //
  355. PersFreshLog->InitHeader(_storage.GetStorageVersion());
  356. newFreshLog.LokCompactLog( PersFreshLog, iter, subst);
  357. return(widNewFreshLog);
  358. }
  359. //+---------------------------------------------------------------------------
  360. //
  361. // Member: CFresh::LokMakeFreshLogBackup
  362. //
  363. // Synopsis: Makes a backup of the current persistent freshlog to the
  364. // storage provided.
  365. //
  366. // Arguments: [storage] - Destination storage.
  367. // [tracker] - Progress tracker and abort indication.
  368. //
  369. // History: 3-18-97 srikants Created
  370. //
  371. //----------------------------------------------------------------------------
  372. void CFresh::LokMakeFreshLogBackup( PStorage & storage,
  373. PSaveProgressTracker & tracker,
  374. XInterface<ICiEnumWorkids> & xEnumWorkids )
  375. {
  376. //
  377. // Create a fresh log with the same name using the storage object
  378. // provided.
  379. //
  380. WORKID widFreshLog = _storage.GetSpecialItObjectId( itFreshLog );
  381. ULONG cRec = 0;
  382. //
  383. // Scope for physical copy of the object.
  384. //
  385. {
  386. //
  387. // Open the source fresh log
  388. //
  389. PRcovStorageObj *pSrcFreshLog = _storage.QueryFreshLog( widFreshLog );
  390. SRcovStorageObj xSrcFreshLog( pSrcFreshLog );
  391. //
  392. // Create the destination fresh log
  393. //
  394. PRcovStorageObj *pDstFreshLog = storage.QueryFreshLog( widFreshLog );
  395. SRcovStorageObj xDstFreshLog( pDstFreshLog );
  396. //
  397. // Copy the contents of the source to the destination.
  398. //
  399. CCopyRcovObject copyData( *pDstFreshLog, *pSrcFreshLog );
  400. NTSTATUS status = copyData.DoIt();
  401. if ( STATUS_SUCCESS != status )
  402. THROW( CException( status ) );
  403. CRcovStorageHdr & hdr = pSrcFreshLog->GetHeader();
  404. cRec = hdr.GetCount( hdr.GetPrimary() );
  405. }
  406. //
  407. // Get the list of WORKIDs in the persistent freshlog.
  408. //
  409. CFreshTest * pFreshTest = new CFreshTest ( max(100,cRec) );
  410. XPtr<CFreshTest> xFreTest( pFreshTest );
  411. SFreshTable freshTable( *pFreshTest );
  412. //
  413. // The source and destination persistent freshlogs are identical.
  414. //
  415. _persFresh.LoadFreshTest( *freshTable );
  416. //
  417. // Copy the workids from freshhash entries to the workid enumerator.
  418. //
  419. CEnumWorkid * pEnumWorkids = new CEnumWorkid( freshTable->Count() );
  420. xEnumWorkids.Set( pEnumWorkids );
  421. for ( CFreshTableIter iter( *freshTable ); !iter.AtEnd(); iter.Advance() )
  422. {
  423. pEnumWorkids->Append( iter->WorkId() );
  424. }
  425. Win4Assert( cRec == freshTable->Count() );
  426. ciDebugOut(( DEB_ITRACE, "%d Workids Changed \n", freshTable->Count() ));
  427. }
  428. //+---------------------------------------------------------------------------
  429. //
  430. // Member: CFresh::LokEmpty, public
  431. //
  432. // Synopsis: Empties/deletes the fresh hash and the fresh log.
  433. //
  434. // History: 16-Aug-94 DwightKr Created
  435. //
  436. //----------------------------------------------------------------------------
  437. void CFresh::LokEmpty()
  438. {
  439. delete _master; // Delete the fresh test
  440. _master = 0;
  441. }