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.

804 lines
27 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation 1997-1998
  5. //
  6. // File: cidump.cxx
  7. //
  8. // Contents: CI catalog dump utility
  9. //
  10. // History: 09-Apr-97 SitaramR Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #define _OLE32_
  14. #define __QUERY__
  15. extern "C"
  16. {
  17. #include <nt.h>
  18. #include <ntioapi.h>
  19. #include <ntrtl.h>
  20. #include <nturtl.h>
  21. }
  22. #include <ctype.h>
  23. #include <float.h>
  24. #include <limits.h>
  25. #include <malloc.h>
  26. #include <math.h>
  27. #include <memory.h>
  28. #include <stddef.h>
  29. #include <string.h>
  30. #include <stdarg.h>
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <windows.h>
  34. #include <imagehlp.h>
  35. #include <lmcons.h>
  36. #define _DCOM_
  37. #define _CAIROSTG_
  38. #include <cidebnot.h>
  39. #include <cierror.h>
  40. #define OLEDBVER 0x0250 // enable ICommandTree interface
  41. #include <oleext.h>
  42. #include <oledberr.h>
  43. #include <oledb.h>
  44. #include <query.h>
  45. #include <stgprop.h>
  46. #include <filter.h>
  47. #include <filterr.h>
  48. #include <vquery.hxx>
  49. #include <restrict.hxx>
  50. //
  51. // Base services
  52. //
  53. #include <ciexcpt.hxx>
  54. #include <smart.hxx>
  55. #include <tsmem.hxx>
  56. #include <xolemem.hxx>
  57. #include <dynarray.hxx>
  58. #include <dynstack.hxx>
  59. #include <dblink.hxx>
  60. #include <cisem.hxx>
  61. #include <thrd32.hxx>
  62. #include <readwrit.hxx>
  63. #include <ci.h>
  64. //
  65. // Debug files from
  66. //
  67. #include <cidebug.hxx>
  68. #include <vqdebug.hxx>
  69. //
  70. // CI-specific
  71. //
  72. #include <align.hxx>
  73. #include <memser.hxx>
  74. #include <memdeser.hxx>
  75. #include <tgrow.hxx>
  76. #include <funypath.hxx>
  77. #include <params.hxx>
  78. #include <key.hxx>
  79. #include <keyarray.hxx>
  80. #include <irest.hxx>
  81. #include <cursor.hxx>
  82. #include <idxids.hxx>
  83. #include <dberror.hxx>
  84. // property-related macros and includes
  85. #include <propapi.h>
  86. #include <propstm.hxx>
  87. extern UNICODECALLOUTS UnicodeCallouts;
  88. #define DebugTrace( x, y, z )
  89. #ifdef PROPASSERTMSG
  90. #undef PROPASSERTMSG
  91. #endif
  92. #define PROPASSERTMSG( x, y )
  93. #include <rcstrmhd.hxx>
  94. #include <xact.hxx>
  95. #include <pidxtbl.hxx>
  96. #include "cistore.hxx"
  97. #include "physidx.hxx"
  98. #include "pcomp.hxx"
  99. #include "cidir.hxx"
  100. DECLARE_INFOLEVEL(ci)
  101. //DECLARE_INFOLEVEL(vq)
  102. //extern BOOL ExceptDllMain( HANDLE hDll, DWORD dwReason, LPVOID lpReserved );
  103. unsigned fVerbose = 0; // Verbose mode dumps all keys, wids and occurrences
  104. unsigned fStats = 0; // Just dump wid/occ counts.
  105. unsigned fFullStats = 0; // Just dump wid/occ counts.
  106. unsigned fKeys = 0; // Key info
  107. unsigned fDistribution = 0; // Key distribution info
  108. unsigned fOccurrences = 0; // Occurrence distribution info
  109. extern "C" GUID CLSID_CTextIFilter = CLSID_TextIFilter;
  110. DWORD Bytes( BitOffset & boff )
  111. {
  112. return ( boff.Page() * CI_PAGE_SIZE ) + ( ( boff.Offset() + 7 ) / 8 );
  113. }
  114. ULONGLONG BitDistance( BitOffset & b1, BitOffset & b2 )
  115. {
  116. ULONGLONG bA = ((ULONGLONG) b1.Page() * (ULONGLONG) ( CI_PAGE_SIZE * 8) ) + b1.Offset();
  117. ULONGLONG bB = ((ULONGLONG) b2.Page() * (ULONGLONG) ( CI_PAGE_SIZE * 8) ) + b2.Offset();
  118. return ( bB - bA );
  119. }
  120. //+---------------------------------------------------------------------------
  121. //
  122. // Function: LocaleToCodepage
  123. //
  124. // Purpose: Returns a codepage from a locale
  125. //
  126. // Arguments: [lcid] -- Locale
  127. //
  128. // History: 09-Apr-97 SitaramR Created
  129. //
  130. //----------------------------------------------------------------------------
  131. ULONG LocaleToCodepage( LCID lcid )
  132. {
  133. const BUFFER_LENGTH = 10;
  134. WCHAR wcsCodePage[BUFFER_LENGTH];
  135. int cwc = GetLocaleInfoW( lcid, LOCALE_IDEFAULTANSICODEPAGE, wcsCodePage, BUFFER_LENGTH );
  136. //
  137. // If error, return Ansi code page
  138. //
  139. if ( cwc == 0 )
  140. {
  141. ciDebugOut(( DEB_ERROR, "GetLocaleInfoW for lcid %d returned %d\n", lcid, GetLastError() ));
  142. return CP_ACP;
  143. }
  144. return wcstoul( wcsCodePage, 0 , 10 );
  145. }
  146. void Usage()
  147. {
  148. printf( "Usage: cidump <catalog path> [-e indexid] [-d] [-s] [-f] [-v] [-w workid]\n"
  149. " -d : Distribution of keys in documents (key, wid, occ)\n"
  150. " -e : Exclude this index\n"
  151. " -k : Print keys with #files, #occ, pid, size\n"
  152. " -s : Stats only\n"
  153. " -f : Full Stats only (for all keys)\n"
  154. " -v : Verbose (full occurrence information)\n"
  155. " -w : Data for this workid only\n\n"
  156. "Example: cidump e:\\testdump\\catalog.wci\n" );
  157. }
  158. void DumpDirectoryKey( unsigned i, CDirectoryKey & Key )
  159. {
  160. BitOffset bo;
  161. Key.Offset( bo );
  162. printf( " key %d cb 0x%x, PropId 0x%x, opage 0x%x, obits 0x%x\n",
  163. i,
  164. Key.Count(),
  165. Key.PropId(),
  166. bo.Page(),
  167. bo.Offset() );
  168. } //DumpDirectoryKey
  169. //+---------------------------------------------------------------------------
  170. //
  171. // Function: main
  172. //
  173. // Purpose: Main dump routine
  174. //
  175. // History: 09-Apr-97 SitaramR Created
  176. // 02-Nov-98 KLam Passed disk space to leave to CiStorage
  177. //
  178. //----------------------------------------------------------------------------
  179. int __cdecl main( int argc, char * argv[] )
  180. {
  181. char * pszCatDir = argv[1];
  182. WORKID widTarget = 0xFFFFFFFF;
  183. INDEXID aExclude[100];
  184. unsigned cExclude = 0;
  185. if ( argc < 2 )
  186. {
  187. Usage();
  188. return 0;
  189. }
  190. for ( int i = 1; i < argc; i++ )
  191. {
  192. if ( argv[i][0] == '-' )
  193. {
  194. switch ( argv[i][1] )
  195. {
  196. case 'e':
  197. case 'E':
  198. i++;
  199. aExclude[cExclude] = strtoul( argv[i], 0, 16 );
  200. cExclude++;
  201. break;
  202. case 's':
  203. case 'S':
  204. fStats = 1;
  205. break;
  206. case 'd':
  207. case 'D':
  208. fDistribution = 1;
  209. break;
  210. case 'f':
  211. case 'F':
  212. fFullStats = 1;
  213. break;
  214. case 'k':
  215. case 'K':
  216. fKeys = 1;
  217. break;
  218. case 'o':
  219. case 'O':
  220. fOccurrences = 1;
  221. break;
  222. case 'v':
  223. case 'V':
  224. fVerbose = 1;
  225. break;
  226. case 'w':
  227. case 'W':
  228. i++;
  229. widTarget = strtoul( argv[i], 0, 10 );
  230. break;
  231. default:
  232. Usage();
  233. return 0;
  234. }
  235. }
  236. else
  237. pszCatDir = argv[i];
  238. }
  239. if ( fKeys )
  240. {
  241. fFullStats = 0;
  242. fStats = 0;
  243. fVerbose = 0;
  244. }
  245. if ( fDistribution )
  246. {
  247. fFullStats = 0;
  248. fStats = 0;
  249. fVerbose = 0;
  250. fKeys = 0;
  251. fOccurrences = 0;
  252. }
  253. if ( fOccurrences )
  254. {
  255. fFullStats = 0;
  256. fStats = 0;
  257. fVerbose = 0;
  258. fKeys = 0;
  259. fDistribution = 0;
  260. }
  261. if ( (pszCatDir[0] != '\\' || pszCatDir[1] != '\\') &&
  262. (pszCatDir[0] == '\0' || pszCatDir[1] != ':' || pszCatDir[2] != '\\') )
  263. {
  264. printf("Use full path name for catalog path!\n\n");
  265. Usage();
  266. return 1;
  267. }
  268. WCHAR wszCatDir[MAX_PATH];
  269. LocaleToCodepage( GetSystemDefaultLCID() );
  270. ULONG cwcActual = MultiByteToWideChar( LocaleToCodepage( GetSystemDefaultLCID() ),
  271. 0,
  272. pszCatDir,
  273. strlen( pszCatDir ) + 1,
  274. wszCatDir,
  275. MAX_PATH );
  276. //ExceptDllMain( 0, DLL_PROCESS_ATTACH, 0 );
  277. //
  278. // Keep stats on where we are when we die...
  279. //
  280. CIndexRecord recCrash;
  281. CKeyBuf keyCrash;
  282. BitOffset boffCrash;
  283. ULONG maxOccCounts = 1024;
  284. TRY
  285. {
  286. ULONGLONG * aOccCounts = new ULONGLONG[ maxOccCounts ];
  287. ULONGLONG * acbOccCounts = new ULONGLONG[ maxOccCounts ];
  288. CTransaction xact;
  289. XPtr<CiStorage> xStorage( new CiStorage( wszCatDir,
  290. *((ICiCAdviseStatus *)0),
  291. CI_MIN_DISK_SPACE_TO_LEAVE_DEFAULT ) );
  292. XPtr<PIndexTable> xIndexTable( xStorage->QueryIndexTable( xact ) );
  293. SIndexTabIter xIndexIter( xIndexTable->QueryIterator() );
  294. if ( xIndexIter->Begin() )
  295. {
  296. CIndexRecord record;
  297. while ( xIndexIter->NextRecord( record ) )
  298. {
  299. if ( record.Type() == itMaster || record.Type() == itShadow )
  300. {
  301. //
  302. // Do we want to skip this one?
  303. //
  304. for ( unsigned i = 0; i < cExclude; i++ )
  305. {
  306. if ( aExclude[i] == record.Iid() )
  307. break;
  308. }
  309. if ( i < cExclude )
  310. continue;
  311. recCrash = record;
  312. boffCrash.Init( 0, 0 );
  313. if ( !fKeys && !fDistribution && !fOccurrences )
  314. {
  315. if ( record.Type() == itMaster )
  316. printf( "Index master: " );
  317. else
  318. printf( "Index shadow: " );
  319. printf( "Object id = 0x%x, Index id = 0x%x, MaxWorkid = 0x%x\n",
  320. record.ObjectId(),
  321. record.Iid(),
  322. record.MaxWorkId() );
  323. }
  324. ULONG maxWid = record.MaxWorkId();
  325. SStorageObject xStorageObj( xStorage->QueryObject( record.ObjectId() ) );
  326. PMmStream * pStream = xStorage->QueryExistingIndexStream( xStorageObj.GetObj(),
  327. PStorage::eOpenForRead );
  328. XPtr<PMmStream> xStream( pStream );
  329. CPhysIndex *pPhysIndex = new CPhysIndex ( *xStorage.GetPointer(),
  330. xStorageObj.GetObj(),
  331. record.ObjectId(),
  332. PStorage::eOpenForRead,
  333. xStream );
  334. Win4Assert( 0 == xStream.GetPointer() );
  335. XPtr<CPhysIndex> xPhysIndex( pPhysIndex );
  336. CiDirectory *pDir = (CiDirectory *) xStorage->QueryExistingDirectory( xStorageObj.GetObj(),
  337. PStorage::eOpenForRead );
  338. XPtr<CiDirectory> xDir( pDir);
  339. unsigned cLevel1 = xDir->Level1Count();
  340. unsigned cLevel2 = xDir->Level2Count();
  341. if ( !fKeys && !fDistribution && !fOccurrences )
  342. {
  343. printf( "directory has %d level 1 and %d level 2 keys\n",
  344. cLevel1, cLevel2 );
  345. if ( fVerbose )
  346. {
  347. for ( unsigned i = 0; i < cLevel1; i++ )
  348. DumpDirectoryKey( i, xDir->GetLevel1Key( i ) );
  349. for ( i = 0; i < cLevel2; i++ )
  350. DumpDirectoryKey( i, xDir->GetLevel2Key( i ) );
  351. }
  352. }
  353. ULONGLONG cOccInIndex = 0;
  354. ULONGLONG cWidsWithOneOcc = 0;
  355. ULONGLONG cWidsWith5OrLessOcc = 0;
  356. ULONGLONG cWidsWithOcc = 0;
  357. ULONG cKeysWithOneWid = 0;
  358. ULONG cKeysInIndex = 0;
  359. ULONG cbMinimumKey = 100000;
  360. ULONG cbMaximumKey = 0;
  361. ULONGLONG cBitsForOcc = 0;
  362. ULONGLONG cBitsForWid = 0;
  363. ULONGLONG cBitsForKey = 0;
  364. ULONG cKeysInMoreThanHalfWids = 0;
  365. ULONG cOccMinOverall = 0xffffffff;
  366. ULONG cOccMaxOverall = 0;
  367. ZeroMemory( aOccCounts, sizeof( ULONGLONG ) * maxOccCounts );
  368. ZeroMemory( acbOccCounts, sizeof( ULONGLONG ) * maxOccCounts );
  369. CPersDeComp *pDecomp = new CPersDeComp( *xDir.GetPointer(),
  370. record.Iid(),
  371. *xPhysIndex.GetPointer(),
  372. record.MaxWorkId(),
  373. TRUE,
  374. TRUE );
  375. XPtr<CPersDeComp> xDecomp( pDecomp );
  376. const CKeyBuf *pKey;
  377. BitOffset off;
  378. xDecomp->GetOffset( off );
  379. BitOffset boffBefore;
  380. boffBefore.Init( 0, 0 );
  381. for ( pKey = xDecomp->GetKey();
  382. pKey != NULL;
  383. pKey = xDecomp->GetNextKey() )
  384. {
  385. BitOffset boAfterKey;
  386. xDecomp->GetOffset( boAfterKey );
  387. cBitsForKey += BitDistance( boffBefore, boAfterKey );
  388. cKeysInIndex++;
  389. keyCrash = *pKey;
  390. xDecomp->GetOffset( boffCrash );
  391. BOOL fFirst = TRUE;
  392. unsigned cWid = 0;
  393. unsigned cOccTotal = 0;
  394. unsigned cOccMin = 0xFFFFFFFF;
  395. unsigned cOccMax = 0;
  396. BitOffset boBeforeWid;
  397. xDecomp->GetOffset( boBeforeWid );
  398. if ( fDistribution )
  399. printf( "%ws", pKey->GetStr() );
  400. for ( WORKID wid = xDecomp->WorkId();
  401. wid != widInvalid;
  402. wid = xDecomp->NextWorkId() )
  403. {
  404. BitOffset boAfterWid;
  405. xDecomp->GetOffset( boAfterWid );
  406. cBitsForWid += BitDistance( boBeforeWid, boAfterWid );
  407. cWidsWithOcc++;
  408. xDecomp->GetOffset( boffCrash );
  409. cWid++;
  410. if ( fFirst )
  411. {
  412. if ( fVerbose || fFullStats || wid == widTarget )
  413. {
  414. printf( " Key size = 0x%x, pid = 0x%x, buffer = %ws, "
  415. "near page %u (0x%x), bit offset %u (0x%x) --> File offset 0x%x\n",
  416. pKey->Count(),
  417. pKey->Pid(),
  418. pKey->GetStr(),
  419. boffCrash.Page(), boffCrash.Page(),
  420. boffCrash.Offset(), boffCrash.Offset(),
  421. boffCrash.Page() * CI_PAGE_SIZE + (boffCrash.Offset() + 7)/8 );
  422. if ( !fKeys )
  423. fFirst = FALSE;
  424. }
  425. }
  426. if ( (fVerbose && 0 == widTarget) ||
  427. wid == widTarget )
  428. printf( "\t wid = 0x%x, MaxOcc = 0x%x, OccCount = 0x%x, "
  429. "near page %u (0x%x), bit offset %u (0x%x) --> File offset 0x%x, "
  430. "\n\t Occurrences = ",
  431. wid,
  432. xDecomp->MaxOccurrence(),
  433. xDecomp->OccurrenceCount(),
  434. boffCrash.Page(), boffCrash.Page(),
  435. boffCrash.Offset(), boffCrash.Offset(),
  436. boffCrash.Page() * CI_PAGE_SIZE + (boffCrash.Offset() + 7)/8 );
  437. unsigned cOcc = 0;
  438. BitOffset bo1;
  439. xDecomp->GetOffset( bo1 );
  440. for ( OCCURRENCE occ = xDecomp->Occurrence();
  441. occ != OCC_INVALID;
  442. occ = xDecomp->NextOccurrence() )
  443. {
  444. xDecomp->GetOffset( boffCrash );
  445. cOcc++;
  446. if ( (fVerbose && 0 == widTarget) ||
  447. wid == widTarget )
  448. printf( "0x%x ", occ );
  449. }
  450. if ( cOcc >= maxOccCounts )
  451. {
  452. ULONG newMax = cOcc * 2;
  453. ULONGLONG *a1 = new ULONGLONG[ newMax ];
  454. ULONGLONG *a2 = new ULONGLONG[ newMax ];
  455. ZeroMemory( a1, sizeof( ULONGLONG ) * newMax );
  456. ZeroMemory( a2, sizeof( ULONGLONG ) * newMax );
  457. RtlCopyMemory( a1, aOccCounts, sizeof( ULONGLONG ) * maxOccCounts );
  458. RtlCopyMemory( a2, acbOccCounts, sizeof( ULONGLONG ) * maxOccCounts );
  459. delete [] aOccCounts;
  460. delete [] acbOccCounts;
  461. aOccCounts = a1;
  462. acbOccCounts = a2;
  463. maxOccCounts = newMax;
  464. }
  465. #if 0
  466. if ( cOcc >= 500 )
  467. {
  468. printf( "cocc %d in wid %d, pid %#x, len %d, %ws\n",
  469. cOcc, wid, pKey->Pid(),
  470. pKey->StrLen(),
  471. pKey->GetStr() );
  472. printf( " cb %d: ", pKey->Count() );
  473. BYTE const * pb = pKey->GetBuf();
  474. for ( ULONG i = 0; i < pKey->Count(); i++ )
  475. printf( " %#x", pb[i] );
  476. printf( "\n" );
  477. }
  478. #endif
  479. BitOffset bo2;
  480. xDecomp->GetOffset( bo2 );
  481. ULONG cDelta = (ULONG) BitDistance( bo1, bo2 );
  482. cBitsForOcc += cDelta;
  483. aOccCounts[ cOcc ]++;
  484. acbOccCounts[ cOcc ] += cDelta;
  485. // if ( fOccurrences )
  486. // printf( "%d, %d\n", cOcc, cDelta );
  487. cOccInIndex += cOcc;
  488. if ( 1 == cOcc )
  489. cWidsWithOneOcc++;
  490. if ( cOcc <= 5 )
  491. cWidsWith5OrLessOcc++;
  492. if ( (fVerbose && 0 == widTarget) ||
  493. wid == widTarget )
  494. printf( "\n" );
  495. cOccTotal += cOcc;
  496. if ( cOcc > cOccMax )
  497. cOccMax = cOcc;
  498. if ( cOcc < cOccMin )
  499. cOccMin = cOcc;
  500. xDecomp->GetOffset( boBeforeWid );
  501. }
  502. if ( 1 == cWid )
  503. cKeysWithOneWid++;
  504. if ( cWid >= ( maxWid/2 ) )
  505. {
  506. printf( "key with >= half wids (%u):\n", cWid );
  507. printf( " pid %#x, len %d, %ws\n",
  508. pKey->Pid(),
  509. pKey->StrLen(),
  510. pKey->GetStr() );
  511. printf( " cb %d: ", pKey->Count() );
  512. BYTE const * pb = pKey->GetBuf();
  513. for ( ULONG i = 0; i < pKey->Count(); i++ )
  514. printf( " %#x", pb[i] );
  515. printf( "\n" );
  516. cKeysInMoreThanHalfWids++;
  517. }
  518. BitOffset boffAfter;
  519. xDecomp->GetOffset( boffAfter );
  520. DWORD b = Bytes( boffAfter ) - Bytes( boffBefore );
  521. if ( b < cbMinimumKey )
  522. cbMinimumKey = b;
  523. if ( b > cbMaximumKey )
  524. cbMaximumKey = b;
  525. // Print this data:
  526. // # of files with the key
  527. // # of occurrences of key in all files
  528. // property id
  529. // # of bytes taken by this key in the index
  530. // string form of the key
  531. //
  532. if ( fKeys )
  533. printf( "%7u %10u %4u %7u %ws\n",
  534. cWid,
  535. cOccTotal,
  536. pKey->Pid(),
  537. b,
  538. pKey->GetStr() );
  539. boffBefore = boffAfter;
  540. if ( cOccMin < cOccMinOverall )
  541. cOccMinOverall = cOccMin;
  542. if ( cOccMax > cOccMaxOverall )
  543. cOccMaxOverall = cOccMax;
  544. if ( fFullStats )
  545. printf( "%u Workid(s), Total Occ = %u, Min Occ = %u, Max Occ = %u\n",
  546. cWid, cOccTotal, cOccMin, cOccMax );
  547. if ( fDistribution )
  548. printf( "! %d! %d\n", cWid, cOccTotal );
  549. }
  550. BitOffset boEnd;
  551. xDecomp->GetOffset( boEnd );
  552. BitOffset boStart;
  553. if ( fOccurrences )
  554. for ( ULONG i = 0; i <= cOccMaxOverall; i++ )
  555. {
  556. printf( "%I64u, ", aOccCounts[ i ] );
  557. printf( "%I64u\n", acbOccCounts[ i ] / 8 );
  558. }
  559. if ( !fDistribution && !fKeys )
  560. {
  561. printf( "cWidsWithOcc %I64u\n", cWidsWithOcc );
  562. printf( "bytes in index: %I64u\n", BitDistance( boStart, boEnd ) / 8 );
  563. printf( "max workid %d\n", maxWid );
  564. printf( "cKeysInIndex: %d\n", cKeysInIndex );
  565. printf( "cOccInIndex %I64u\n", cOccInIndex );
  566. printf( "cWidsWithOneOcc %I64u\n", cWidsWithOneOcc );
  567. printf( "cWidsWith5OrLessOcc %I64u\n", cWidsWith5OrLessOcc );
  568. printf( "cKeysWithOneWid %d\n", cKeysWithOneWid );
  569. printf( "cKeysInMoreThanHalfWids %d\n", cKeysInMoreThanHalfWids );
  570. printf( "cOccMaxOverall %d\n", cOccMaxOverall );
  571. printf( "cOccMinOverall %d\n", cOccMinOverall );
  572. printf( "maximum key bytes %d\n", cbMaximumKey );
  573. printf( "minimum key bytes %d\n", cbMinimumKey );
  574. printf( "bytes for occ data: %I64u\n", ( cBitsForOcc / 8 ) );
  575. printf( "bytes for key data: %I64u\n", ( cBitsForKey / 8 ) );
  576. printf( "bytes for wid data: %I64u\n", ( cBitsForWid / 8 ) );
  577. printf( "total for o+k+w data: %I64u\n", ( cBitsForOcc/8 + cBitsForKey/8 + cBitsForWid/8 ) );
  578. }
  579. }
  580. else if ( !fKeys && !fDistribution && !fOccurrences )
  581. {
  582. switch ( record.Type() )
  583. {
  584. case itZombie:
  585. printf( "Zombie: " );
  586. break;
  587. case itDeleted:
  588. printf( "Deleted: " );
  589. break;
  590. case itPartition:
  591. printf( "Partition: " );
  592. break;
  593. case itChangeLog:
  594. printf( "ChangeLog: " );
  595. break;
  596. case itFreshLog:
  597. printf( "FreshLog: " );
  598. break;
  599. case itPhraseLat:
  600. printf( "Phrase Lat: " );
  601. break;
  602. case itKeyList:
  603. printf( "Key List: " );
  604. break;
  605. case itMMLog:
  606. printf( "MM Log: " );
  607. break;
  608. case itNewMaster:
  609. printf( "New Master: " );
  610. break;
  611. case itMMKeyList:
  612. printf( "MM Key List: " );
  613. break;
  614. } // switch
  615. printf( "Object id = 0x%x, Index id = 0x%x, MaxWorkid = 0x%x\n",
  616. record.ObjectId(),
  617. record.Iid(),
  618. record.MaxWorkId() );
  619. } // if
  620. } // while
  621. } // if
  622. else
  623. printf( "0 records found in index table\n" );
  624. delete [] aOccCounts;
  625. delete [] acbOccCounts;
  626. }
  627. CATCH( CException, e )
  628. {
  629. if ( HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION) == e.GetErrorCode() )
  630. {
  631. printf("Sharing violation -- Is cisvc running?\n");
  632. }
  633. else
  634. {
  635. printf( "Caught exception 0x%x in %s 0x%x\n",
  636. e.GetErrorCode(),
  637. ( recCrash.Type() == itMaster ) ? "master index" : "shadow index",
  638. recCrash.Iid() );
  639. printf( "\tProcessing key: %ws (pid = 0x%x)\n", keyCrash.GetStr(), keyCrash.Pid() );
  640. printf( "\tNear page %u (0x%x), bit offset %u (0x%x) --> File offset 0x%x\n",
  641. boffCrash.Page(), boffCrash.Page(),
  642. boffCrash.Offset(), boffCrash.Offset(),
  643. boffCrash.Page() * CI_PAGE_SIZE + (boffCrash.Offset() + 7)/8 );
  644. }
  645. }
  646. END_CATCH
  647. return 0;
  648. }