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.

808 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. if ( 0 == cwcActual )
  277. {
  278. Usage();
  279. return 1;
  280. }
  281. //
  282. // Keep stats on where we are when we die...
  283. //
  284. CIndexRecord recCrash;
  285. CKeyBuf keyCrash;
  286. BitOffset boffCrash;
  287. ULONG maxOccCounts = 1024;
  288. TRY
  289. {
  290. ULONGLONG * aOccCounts = new ULONGLONG[ maxOccCounts ];
  291. ULONGLONG * acbOccCounts = new ULONGLONG[ maxOccCounts ];
  292. CTransaction xact;
  293. XPtr<CiStorage> xStorage( new CiStorage( wszCatDir,
  294. *((ICiCAdviseStatus *)0),
  295. CI_MIN_DISK_SPACE_TO_LEAVE_DEFAULT ) );
  296. XPtr<PIndexTable> xIndexTable( xStorage->QueryIndexTable( xact ) );
  297. SIndexTabIter xIndexIter( xIndexTable->QueryIterator() );
  298. if ( xIndexIter->Begin() )
  299. {
  300. CIndexRecord record;
  301. while ( xIndexIter->NextRecord( record ) )
  302. {
  303. if ( record.Type() == itMaster || record.Type() == itShadow )
  304. {
  305. //
  306. // Do we want to skip this one?
  307. //
  308. for ( unsigned i = 0; i < cExclude; i++ )
  309. {
  310. if ( aExclude[i] == record.Iid() )
  311. break;
  312. }
  313. if ( i < cExclude )
  314. continue;
  315. recCrash = record;
  316. boffCrash.Init( 0, 0 );
  317. if ( !fKeys && !fDistribution && !fOccurrences )
  318. {
  319. if ( record.Type() == itMaster )
  320. printf( "Index master: " );
  321. else
  322. printf( "Index shadow: " );
  323. printf( "Object id = 0x%x, Index id = 0x%x, MaxWorkid = 0x%x\n",
  324. record.ObjectId(),
  325. record.Iid(),
  326. record.MaxWorkId() );
  327. }
  328. ULONG maxWid = record.MaxWorkId();
  329. SStorageObject xStorageObj( xStorage->QueryObject( record.ObjectId() ) );
  330. PMmStream * pStream = xStorage->QueryExistingIndexStream( xStorageObj.GetObj(),
  331. PStorage::eOpenForRead );
  332. XPtr<PMmStream> xStream( pStream );
  333. CPhysIndex *pPhysIndex = new CPhysIndex ( *xStorage.GetPointer(),
  334. xStorageObj.GetObj(),
  335. record.ObjectId(),
  336. PStorage::eOpenForRead,
  337. xStream );
  338. Win4Assert( 0 == xStream.GetPointer() );
  339. XPtr<CPhysIndex> xPhysIndex( pPhysIndex );
  340. CiDirectory *pDir = (CiDirectory *) xStorage->QueryExistingDirectory( xStorageObj.GetObj(),
  341. PStorage::eOpenForRead );
  342. XPtr<CiDirectory> xDir( pDir);
  343. unsigned cLevel1 = xDir->Level1Count();
  344. unsigned cLevel2 = xDir->Level2Count();
  345. if ( !fKeys && !fDistribution && !fOccurrences )
  346. {
  347. printf( "directory has %d level 1 and %d level 2 keys\n",
  348. cLevel1, cLevel2 );
  349. if ( fVerbose )
  350. {
  351. for ( unsigned i = 0; i < cLevel1; i++ )
  352. DumpDirectoryKey( i, xDir->GetLevel1Key( i ) );
  353. for ( i = 0; i < cLevel2; i++ )
  354. DumpDirectoryKey( i, xDir->GetLevel2Key( i ) );
  355. }
  356. }
  357. ULONGLONG cOccInIndex = 0;
  358. ULONGLONG cWidsWithOneOcc = 0;
  359. ULONGLONG cWidsWith5OrLessOcc = 0;
  360. ULONGLONG cWidsWithOcc = 0;
  361. ULONG cKeysWithOneWid = 0;
  362. ULONG cKeysInIndex = 0;
  363. ULONG cbMinimumKey = 100000;
  364. ULONG cbMaximumKey = 0;
  365. ULONGLONG cBitsForOcc = 0;
  366. ULONGLONG cBitsForWid = 0;
  367. ULONGLONG cBitsForKey = 0;
  368. ULONG cKeysInMoreThanHalfWids = 0;
  369. ULONG cOccMinOverall = 0xffffffff;
  370. ULONG cOccMaxOverall = 0;
  371. ZeroMemory( aOccCounts, sizeof( ULONGLONG ) * maxOccCounts );
  372. ZeroMemory( acbOccCounts, sizeof( ULONGLONG ) * maxOccCounts );
  373. CPersDeComp *pDecomp = new CPersDeComp( *xDir.GetPointer(),
  374. record.Iid(),
  375. *xPhysIndex.GetPointer(),
  376. record.MaxWorkId(),
  377. TRUE,
  378. TRUE );
  379. XPtr<CPersDeComp> xDecomp( pDecomp );
  380. const CKeyBuf *pKey;
  381. BitOffset off;
  382. xDecomp->GetOffset( off );
  383. BitOffset boffBefore;
  384. boffBefore.Init( 0, 0 );
  385. for ( pKey = xDecomp->GetKey();
  386. pKey != NULL;
  387. pKey = xDecomp->GetNextKey() )
  388. {
  389. BitOffset boAfterKey;
  390. xDecomp->GetOffset( boAfterKey );
  391. cBitsForKey += BitDistance( boffBefore, boAfterKey );
  392. cKeysInIndex++;
  393. keyCrash = *pKey;
  394. xDecomp->GetOffset( boffCrash );
  395. BOOL fFirst = TRUE;
  396. unsigned cWid = 0;
  397. unsigned cOccTotal = 0;
  398. unsigned cOccMin = 0xFFFFFFFF;
  399. unsigned cOccMax = 0;
  400. BitOffset boBeforeWid;
  401. xDecomp->GetOffset( boBeforeWid );
  402. if ( fDistribution )
  403. printf( "%ws", pKey->GetStr() );
  404. for ( WORKID wid = xDecomp->WorkId();
  405. wid != widInvalid;
  406. wid = xDecomp->NextWorkId() )
  407. {
  408. BitOffset boAfterWid;
  409. xDecomp->GetOffset( boAfterWid );
  410. cBitsForWid += BitDistance( boBeforeWid, boAfterWid );
  411. cWidsWithOcc++;
  412. xDecomp->GetOffset( boffCrash );
  413. cWid++;
  414. if ( fFirst )
  415. {
  416. if ( fVerbose || fFullStats || wid == widTarget )
  417. {
  418. printf( " Key size = 0x%x, pid = 0x%x, buffer = %ws, "
  419. "near page %u (0x%x), bit offset %u (0x%x) --> File offset 0x%x\n",
  420. pKey->Count(),
  421. pKey->Pid(),
  422. pKey->GetStr(),
  423. boffCrash.Page(), boffCrash.Page(),
  424. boffCrash.Offset(), boffCrash.Offset(),
  425. boffCrash.Page() * CI_PAGE_SIZE + (boffCrash.Offset() + 7)/8 );
  426. if ( !fKeys )
  427. fFirst = FALSE;
  428. }
  429. }
  430. if ( (fVerbose && 0 == widTarget) ||
  431. wid == widTarget )
  432. printf( "\t wid = 0x%x, MaxOcc = 0x%x, OccCount = 0x%x, "
  433. "near page %u (0x%x), bit offset %u (0x%x) --> File offset 0x%x, "
  434. "\n\t Occurrences = ",
  435. wid,
  436. xDecomp->MaxOccurrence(),
  437. xDecomp->OccurrenceCount(),
  438. boffCrash.Page(), boffCrash.Page(),
  439. boffCrash.Offset(), boffCrash.Offset(),
  440. boffCrash.Page() * CI_PAGE_SIZE + (boffCrash.Offset() + 7)/8 );
  441. unsigned cOcc = 0;
  442. BitOffset bo1;
  443. xDecomp->GetOffset( bo1 );
  444. for ( OCCURRENCE occ = xDecomp->Occurrence();
  445. occ != OCC_INVALID;
  446. occ = xDecomp->NextOccurrence() )
  447. {
  448. xDecomp->GetOffset( boffCrash );
  449. cOcc++;
  450. if ( (fVerbose && 0 == widTarget) ||
  451. wid == widTarget )
  452. printf( "0x%x ", occ );
  453. }
  454. if ( cOcc >= maxOccCounts )
  455. {
  456. ULONG newMax = cOcc * 2;
  457. ULONGLONG *a1 = new ULONGLONG[ newMax ];
  458. ULONGLONG *a2 = new ULONGLONG[ newMax ];
  459. ZeroMemory( a1, sizeof( ULONGLONG ) * newMax );
  460. ZeroMemory( a2, sizeof( ULONGLONG ) * newMax );
  461. RtlCopyMemory( a1, aOccCounts, sizeof( ULONGLONG ) * maxOccCounts );
  462. RtlCopyMemory( a2, acbOccCounts, sizeof( ULONGLONG ) * maxOccCounts );
  463. delete [] aOccCounts;
  464. delete [] acbOccCounts;
  465. aOccCounts = a1;
  466. acbOccCounts = a2;
  467. maxOccCounts = newMax;
  468. }
  469. #if 0
  470. if ( cOcc >= 500 )
  471. {
  472. printf( "cocc %d in wid %d, pid %#x, len %d, %ws\n",
  473. cOcc, wid, pKey->Pid(),
  474. pKey->StrLen(),
  475. pKey->GetStr() );
  476. printf( " cb %d: ", pKey->Count() );
  477. BYTE const * pb = pKey->GetBuf();
  478. for ( ULONG i = 0; i < pKey->Count(); i++ )
  479. printf( " %#x", pb[i] );
  480. printf( "\n" );
  481. }
  482. #endif
  483. BitOffset bo2;
  484. xDecomp->GetOffset( bo2 );
  485. ULONG cDelta = (ULONG) BitDistance( bo1, bo2 );
  486. cBitsForOcc += cDelta;
  487. aOccCounts[ cOcc ]++;
  488. acbOccCounts[ cOcc ] += cDelta;
  489. // if ( fOccurrences )
  490. // printf( "%d, %d\n", cOcc, cDelta );
  491. cOccInIndex += cOcc;
  492. if ( 1 == cOcc )
  493. cWidsWithOneOcc++;
  494. if ( cOcc <= 5 )
  495. cWidsWith5OrLessOcc++;
  496. if ( (fVerbose && 0 == widTarget) ||
  497. wid == widTarget )
  498. printf( "\n" );
  499. cOccTotal += cOcc;
  500. if ( cOcc > cOccMax )
  501. cOccMax = cOcc;
  502. if ( cOcc < cOccMin )
  503. cOccMin = cOcc;
  504. xDecomp->GetOffset( boBeforeWid );
  505. }
  506. if ( 1 == cWid )
  507. cKeysWithOneWid++;
  508. if ( cWid >= ( maxWid/2 ) )
  509. {
  510. printf( "key with >= half wids (%u):\n", cWid );
  511. printf( " pid %#x, len %d, %ws\n",
  512. pKey->Pid(),
  513. pKey->StrLen(),
  514. pKey->GetStr() );
  515. printf( " cb %d: ", pKey->Count() );
  516. BYTE const * pb = pKey->GetBuf();
  517. for ( ULONG i = 0; i < pKey->Count(); i++ )
  518. printf( " %#x", pb[i] );
  519. printf( "\n" );
  520. cKeysInMoreThanHalfWids++;
  521. }
  522. BitOffset boffAfter;
  523. xDecomp->GetOffset( boffAfter );
  524. DWORD b = Bytes( boffAfter ) - Bytes( boffBefore );
  525. if ( b < cbMinimumKey )
  526. cbMinimumKey = b;
  527. if ( b > cbMaximumKey )
  528. cbMaximumKey = b;
  529. // Print this data:
  530. // # of files with the key
  531. // # of occurrences of key in all files
  532. // property id
  533. // # of bytes taken by this key in the index
  534. // string form of the key
  535. //
  536. if ( fKeys )
  537. printf( "%7u %10u %4u %7u %ws\n",
  538. cWid,
  539. cOccTotal,
  540. pKey->Pid(),
  541. b,
  542. pKey->GetStr() );
  543. boffBefore = boffAfter;
  544. if ( cOccMin < cOccMinOverall )
  545. cOccMinOverall = cOccMin;
  546. if ( cOccMax > cOccMaxOverall )
  547. cOccMaxOverall = cOccMax;
  548. if ( fFullStats )
  549. printf( "%u Workid(s), Total Occ = %u, Min Occ = %u, Max Occ = %u\n",
  550. cWid, cOccTotal, cOccMin, cOccMax );
  551. if ( fDistribution )
  552. printf( "! %d! %d\n", cWid, cOccTotal );
  553. }
  554. BitOffset boEnd;
  555. xDecomp->GetOffset( boEnd );
  556. BitOffset boStart;
  557. if ( fOccurrences )
  558. for ( ULONG i = 0; i <= cOccMaxOverall; i++ )
  559. {
  560. printf( "%I64u, ", aOccCounts[ i ] );
  561. printf( "%I64u\n", acbOccCounts[ i ] / 8 );
  562. }
  563. if ( !fDistribution && !fKeys )
  564. {
  565. printf( "cWidsWithOcc %I64u\n", cWidsWithOcc );
  566. printf( "bytes in index: %I64u\n", BitDistance( boStart, boEnd ) / 8 );
  567. printf( "max workid %d\n", maxWid );
  568. printf( "cKeysInIndex: %d\n", cKeysInIndex );
  569. printf( "cOccInIndex %I64u\n", cOccInIndex );
  570. printf( "cWidsWithOneOcc %I64u\n", cWidsWithOneOcc );
  571. printf( "cWidsWith5OrLessOcc %I64u\n", cWidsWith5OrLessOcc );
  572. printf( "cKeysWithOneWid %d\n", cKeysWithOneWid );
  573. printf( "cKeysInMoreThanHalfWids %d\n", cKeysInMoreThanHalfWids );
  574. printf( "cOccMaxOverall %d\n", cOccMaxOverall );
  575. printf( "cOccMinOverall %d\n", cOccMinOverall );
  576. printf( "maximum key bytes %d\n", cbMaximumKey );
  577. printf( "minimum key bytes %d\n", cbMinimumKey );
  578. printf( "bytes for occ data: %I64u\n", ( cBitsForOcc / 8 ) );
  579. printf( "bytes for key data: %I64u\n", ( cBitsForKey / 8 ) );
  580. printf( "bytes for wid data: %I64u\n", ( cBitsForWid / 8 ) );
  581. printf( "total for o+k+w data: %I64u\n", ( cBitsForOcc/8 + cBitsForKey/8 + cBitsForWid/8 ) );
  582. }
  583. }
  584. else if ( !fKeys && !fDistribution && !fOccurrences )
  585. {
  586. switch ( record.Type() )
  587. {
  588. case itZombie:
  589. printf( "Zombie: " );
  590. break;
  591. case itDeleted:
  592. printf( "Deleted: " );
  593. break;
  594. case itPartition:
  595. printf( "Partition: " );
  596. break;
  597. case itChangeLog:
  598. printf( "ChangeLog: " );
  599. break;
  600. case itFreshLog:
  601. printf( "FreshLog: " );
  602. break;
  603. case itPhraseLat:
  604. printf( "Phrase Lat: " );
  605. break;
  606. case itKeyList:
  607. printf( "Key List: " );
  608. break;
  609. case itMMLog:
  610. printf( "MM Log: " );
  611. break;
  612. case itNewMaster:
  613. printf( "New Master: " );
  614. break;
  615. case itMMKeyList:
  616. printf( "MM Key List: " );
  617. break;
  618. } // switch
  619. printf( "Object id = 0x%x, Index id = 0x%x, MaxWorkid = 0x%x\n",
  620. record.ObjectId(),
  621. record.Iid(),
  622. record.MaxWorkId() );
  623. } // if
  624. } // while
  625. } // if
  626. else
  627. printf( "0 records found in index table\n" );
  628. delete [] aOccCounts;
  629. delete [] acbOccCounts;
  630. }
  631. CATCH( CException, e )
  632. {
  633. if ( HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION) == e.GetErrorCode() )
  634. {
  635. printf("Sharing violation -- Is cisvc running?\n");
  636. }
  637. else
  638. {
  639. printf( "Caught exception 0x%x in %s 0x%x\n",
  640. e.GetErrorCode(),
  641. ( recCrash.Type() == itMaster ) ? "master index" : "shadow index",
  642. recCrash.Iid() );
  643. printf( "\tProcessing key: %ws (pid = 0x%x)\n", keyCrash.GetStr(), keyCrash.Pid() );
  644. printf( "\tNear page %u (0x%x), bit offset %u (0x%x) --> File offset 0x%x\n",
  645. boffCrash.Page(), boffCrash.Page(),
  646. boffCrash.Offset(), boffCrash.Offset(),
  647. boffCrash.Page() * CI_PAGE_SIZE + (boffCrash.Offset() + 7)/8 );
  648. }
  649. }
  650. END_CATCH
  651. return 0;
  652. }