/*++ Copyright (c) 1989 Microsoft Corporation Module Name: scan.cpp Abstract: This module contains the scanning code for the chkhash program. Author: Johnson Apacible (JohnsonA) 25-Sept-1995 Revision History: --*/ #include "..\..\tigris.hxx" #include "chkhash.h" VOID PrintHeadStats( PHASH_RESERVED_PAGE Head ) { if ( !Verbose ) { return; } printf("Signature [%x]\n",Head->Signature); printf("Pages %d",Head->NumPages); printf("\t\t\tDir depth %d\n",Head->DirDepth); printf("Insertions %d",Head->InsertionCount); printf("\t\tDeletions %d\n",Head->DeletionCount); printf("Searches %d",Head->SearchCount); printf("\t\tSplits %d\n",Head->PageSplits); printf("Dir expansions %d",Head->DirExpansions); printf("\tTable expansions %d\n",Head->TableExpansions); printf("Duplicate Inserts %d\n",Head->DupInserts); } // PrintHeadStats VOID PrintPageStats( PHTABLE HTable, PMAP_PAGE Page ) { DWORD nDel = 0; DWORD nOk = 0; DWORD j; SHORT offset; if ( Verbose ) { printf("Hash prefix %x\t\tDepth %d\n",Page->HashPrefix,Page->PageDepth); printf("Entries %d",Page->EntryCount); printf("\t\tUndel Entries %d\n",Page->ActualCount); printf("Flag %x",Page->Flags); printf("\t\t\tBytes Available %d\n", Page->LastFree-Page->NextFree); if ( Page->FragmentedBytes != 0 ) { printf("Fragmented bytes %d\n", Page->FragmentedBytes); } } HTable->Entries += Page->EntryCount; // // Make sure entries are correct // for (j=0; jArtOffset[j]; if ( offset != 0 ) { if ( offset < 0 ) { nDel++; continue; } nOk++; // // Make sure hash values are mapped to correct pages // if ( Page->PageDepth == 0 ) { // // if PageDepth is zero, then everything is ok. // continue; } if ( HTable->Signature == ART_HEAD_SIGNATURE ) { PART_MAP_ENTRY aEntry; aEntry = (PART_MAP_ENTRY)((PCHAR)Page + offset); if ( Page->HashPrefix != (aEntry->Header.HashValue >> (32 - Page->PageDepth)) ) { printf("Invalid: HashValue %x\n",aEntry->Header.HashValue); HTable->Flags |= HASH_FLAG_BAD_HASH; } } else if ( HTable->Signature == HIST_HEAD_SIGNATURE ) { PHISTORY_MAP_ENTRY hEntry; hEntry = (PHISTORY_MAP_ENTRY)((PCHAR)Page + offset); if ( Page->HashPrefix != (hEntry->Header.HashValue >> (32 - Page->PageDepth)) ) { printf("Invalid: HashValue %x\n",hEntry->Header.HashValue); HTable->Flags |= HASH_FLAG_BAD_HASH; } } else if ( HTable->Signature == XOVER_HEAD_SIGNATURE ) { PXOVER_MAP_ENTRY xEntry; xEntry = (PXOVER_MAP_ENTRY)((PCHAR)Page + offset); if ( Page->HashPrefix != (xEntry->Header.HashValue >> (32 - Page->PageDepth)) ) { printf("Invalid: HashValue %x\n",xEntry->Header.HashValue); HTable->Flags |= HASH_FLAG_BAD_HASH; } } } } // // Check to see that all numbers are consistent // if ( nDel + nOk != Page->EntryCount ) { printf("!!!!!!! counts don't match\n"); HTable->Flags |= HASH_FLAG_BAD_ENTRY_COUNT; } if ( Verbose ) { printf("Deleted %d Ok %d Total %d\n\n",nDel,nOk,nDel+nOk); } HTable->TotDels += nDel; HTable->TotIns += nOk; } // PrintPageStats BOOL checklink( PHTABLE HTable ) { DWORD fileSize = 0; DWORD nPages; HANDLE hFile = INVALID_HANDLE_VALUE, hMap = NULL; PMAP_PAGE hashPages = NULL; PHASH_RESERVED_PAGE headPage = NULL; DWORD dirDepth; DWORD nEntries; PDWORD directory = NULL; PMAP_PAGE curPage; DWORD i; DWORD j; DWORD status; BOOL ret = FALSE; // // Open the hash file // hFile = CreateFile( HTable->FileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if ( hFile == INVALID_HANDLE_VALUE ) { status = GetLastError(); if ( status == ERROR_FILE_NOT_FOUND ) { HTable->Flags |= HASH_FLAG_NO_FILE; if ( Verbose ) { printf("File not found\n"); } } else { HTable->Flags |= HASH_FLAG_ABORT_SCAN; printf("Error %d in CreateFile.\n",status); } goto error; } // // Get the size of the file. This will tell us how many pages // are currently filled. // fileSize = GetFileSize( hFile, NULL ); if ( fileSize == 0xffffffff ) { status = GetLastError(); printf("Error %d in GetFileSize\n",status); HTable->Flags |= HASH_FLAG_ABORT_SCAN; goto error; } if ( Verbose ) { printf("File size is %d\n",fileSize); } HTable->FileSize = fileSize; // // Make sure the file size is a multiple of a page // if ( (fileSize % HASH_PAGE_SIZE) != 0 ) { // // Not a page multiple! Corrupted! // printf("File size(%d) is not page multiple.\n",fileSize); HTable->Flags |= HASH_FLAG_BAD_SIZE; goto error; } nPages = fileSize / HASH_PAGE_SIZE; if ( Verbose ) { printf("pages allocated %d\n", nPages); } // // Create File Mapping // hMap = CreateFileMapping( hFile, NULL, PAGE_READWRITE, 0, 0, NULL ); if ( hMap == NULL ) { status = GetLastError(); printf("Error %d in CreateFileMapping\n",status); HTable->Flags |= HASH_FLAG_ABORT_SCAN; goto error; } // // create our view // headPage = (PHASH_RESERVED_PAGE)MapViewOfFileEx( hMap, FILE_MAP_ALL_ACCESS, 0, // offset high 0, // offset low 0, // bytes to map NULL // base address ); if ( headPage == NULL ) { status = GetLastError(); printf("Error %d in MapViewOfFile\n",status); HTable->Flags |= HASH_FLAG_ABORT_SCAN; goto error; } // // Print out the header stats // PrintHeadStats( headPage ); // // Check the signature and the initialize bit // if ( headPage->Signature != HTable->Signature ) { // // Wrong signature // printf("Invalid signature %x (expected %x)\n", headPage->Signature, HTable->Signature); HTable->Flags |= HASH_FLAG_BAD_SIGN; goto error; } if ( !headPage->Initialized ) { // // Not initialized ! // printf("Existing file uninitialized!!!!.\n"); HTable->Flags |= HASH_FLAG_NOT_INIT; goto error; } if ( headPage->NumPages > nPages ) { // // bad count. Corrupt file. // printf("NumPages in Header(%d) more than actual(%d)\n", headPage->NumPages, nPages); HTable->Flags |= HASH_FLAG_BAD_PAGE_COUNT; goto error; } // // Create links and print stats for each page // nPages = headPage->NumPages; dirDepth = headPage->DirDepth; hashPages = (PMAP_PAGE)((PCHAR)headPage + HASH_PAGE_SIZE); // // OK, build the directory // nEntries = (DWORD)(1 << dirDepth); if ( nEntries <= nPages ) { printf("dir depth is not sufficient for pages\n"); HTable->Flags |= HASH_FLAG_BAD_DIR_DEPTH; goto error; } if ( Verbose ) { printf("\nSetting up directory of %d entries\n",nEntries); } directory = (PDWORD)ALLOCATE_HEAP( nEntries * sizeof(DWORD) ); if ( directory == NULL ) { printf("Cannot allocate directory of %d entries!!!\n",nEntries); HTable->Flags |= HASH_FLAG_ABORT_SCAN; goto error; } // // Initialize the directory to zero. // ZeroMemory( directory, nEntries * sizeof(DWORD) ); // // Initialize the links. Here we go through all the pages and update the directory // links // curPage = hashPages; for ( i = 1; i < nPages; i++ ) { // // Set the pointers for this page // DWORD startPage, endPage; DWORD j; if ( Verbose ) { printf("Processing page %d\n",i); } // // Get the range of directory entries that point to this page // startPage = curPage->HashPrefix << (dirDepth - curPage->PageDepth); endPage = ((curPage->HashPrefix+1) << (dirDepth - curPage->PageDepth)); if ( Verbose ) { printf("\tDirectory ptrs <%d:%d>\n",startPage,endPage-1); } if ( (startPage > nEntries) || (endPage > nEntries) ) { printf("Corrupt prefix for page %d\n",i); HTable->Flags |= HASH_FLAG_CORRUPT; goto error; } for ( j = startPage; j < endPage; j++ ) { directory[j] = i; } // // Print page stats // PrintPageStats( HTable, curPage ); // // go to the next page // curPage = (PMAP_PAGE)((PCHAR)curPage + HASH_PAGE_SIZE); } // // Make sure all the links have been initialized. If not, then something terrible // has happened. Do a comprehensive rebuilt. // for (i=0;iFlags |= HASH_FLAG_BAD_LINK; goto error; } } ret = TRUE; error: // // Delete the Directory // if ( directory != NULL ) { FREE_HEAP(directory); directory = NULL; } // // Destroy the view // if ( headPage != NULL ) { // // Flush the hash table // (VOID)FlushViewOfFile( headPage, 0 ); // // Close the view // (VOID) UnmapViewOfFile( headPage ); headPage = NULL; } // // Destroy the file mapping // if ( hMap != NULL ) { CloseHandle( hMap ); hMap = NULL; } // // Close the file // if ( hFile != INVALID_HANDLE_VALUE ) { CloseHandle( hFile ); hFile = INVALID_HANDLE_VALUE; } return(ret); } // chklink BOOL diagnose( PHTABLE HTable ) { DWORD flags = HTable->Flags; printf("Status: "); if ( flags == 0 ) { printf("Good.\n"); return(TRUE); } // // Missing? // if ( flags & HASH_FLAG_NO_FILE ) { if ( !DoClean ) { printf("Missing File.\n"); } goto exit; } if ( flags & HASH_FLAG_ABORT_SCAN ) { printf("Internal error occurred while processing.\n"); goto exit; } printf("Corrupt. Diagnostic Code %x.\n",flags); exit: return(FALSE); }