/**************************************************************************** Desc: Determines the values of the parameters needed to reference a specific SCache block. Must be called from within a mutex ****************************************************************************/ FSTATIC void flmBuildSCacheBlockString( char * pszString, SCACHE * pSCache) { char szAddress[ 20]; if ((pSCache == NULL) || (pSCache->pFile == NULL)) { pszString[0] = 0; } else { printAddress( pSCache->pFile, szAddress); f_sprintf( (char *)pszString, "%s/SCacheBlock?BlockAddress=%lu&File=%s&LowTransID=%lu&HighTransID=%lu", gv_FlmSysData.HttpConfigParms.pszURLString, pSCache->uiBlkAddress, szAddress, scaGetLowTransID( pSCache), pSCache->uiHighTransID); } return; }
/**************************************************************************** Desc: Searches the SCache for the block referenced by the parameters. If found, it copies the data into pLocalSCache. Assumes that the mutex has already been locked! ****************************************************************************/ RCODE F_SCacheBase::locateSCacheBlock( FLMUINT uiNumParams, const char ** ppszParams, SCACHE * pLocalSCache, FLMUINT * puiBlkAddress, FLMUINT * puiLowTransID, FLMUINT * puiHighTransID, FFILE * * ppFile) { RCODE rc = FERR_OK; FLMUINT uiSigBitsInBlkSize; SCACHE * pSCache; SCACHE ** ppSCache; #define MAXPARAMLEN 15 char szBlkAddress[MAXPARAMLEN]; char szLowTransID[MAXPARAMLEN]; char szHighTransID[MAXPARAMLEN]; char szFile[MAXPARAMLEN]; // Grab the block address, low and high trans id's and FFile pointer, which // we need to uniquely identify an scache block... if (RC_BAD( rc = ExtractParameter( uiNumParams, ppszParams, "BlockAddress", sizeof( szBlkAddress), &szBlkAddress[0]))) { goto Exit; } *puiBlkAddress = f_atoi( szBlkAddress); if (RC_BAD( rc = ExtractParameter( uiNumParams, ppszParams, "LowTransID", sizeof( szLowTransID), &szLowTransID[0]))) { goto Exit; } *puiLowTransID = f_atoi( szLowTransID); if (RC_BAD( rc = ExtractParameter( uiNumParams, ppszParams, "HighTransID", sizeof( szHighTransID), &szHighTransID[0]))) { goto Exit; } *puiHighTransID = f_atoi( szHighTransID); if (RC_BAD( rc = ExtractParameter( uiNumParams, ppszParams, "File", sizeof( szFile), &szFile[0]))) { goto Exit; } *ppFile = (FFILE *)f_atoud( szFile); flmAssert( *ppFile); uiSigBitsInBlkSize = (*ppFile)->FileHdr.uiSigBitsInBlkSize; // ScaHash actually returns a pointer to the first scache in the hash // bucket. It's up to us to traverse this list to find the proper block // address and FFile (and potentially high and low trans id) ppSCache = ScaHash( uiSigBitsInBlkSize, *puiBlkAddress); pSCache = *ppSCache; while ( pSCache && ( (pSCache->uiBlkAddress != *puiBlkAddress) || (pSCache->pFile != *ppFile) ) ) { pSCache = pSCache->pNextInHashBucket; } // Ok - we've found the right address and ffile. Do we need a different // version? while ( (pSCache) && (pSCache->uiHighTransID != *puiHighTransID) && (scaGetLowTransID( pSCache) != *puiLowTransID) ) { pSCache = pSCache->pNextInVersionList; } // Now, if we've found the right block, copy it's contents to local memory... if (pSCache) { f_memcpy( pLocalSCache, pSCache, sizeof( SCACHE)); } else { rc = RC_SET( FERR_NOT_FOUND); goto Exit; } Exit: return( rc); }
/**************************************************************************** Desc: This function handle the details of extracting the parameters needed to interpret the request and then generating the response HTML page ****************************************************************************/ RCODE F_FFilePage::display( FLMUINT uiNumParams, const char ** ppszParams) { RCODE rc = FERR_OK; #define GENERIC_SIZE_B 20 char szFrom[ GENERIC_SIZE_B]; char szBucket[ 4]; FLMUINT uiBucket; FFILE localFFile; FFILE * pFile; FLMBOOL bRefresh; void * pvAddress; char szAddress[GENERIC_SIZE_B]; char szLink[GENERIC_SIZE_B]; FLMBOOL bFlmLocked = FALSE; DATASTRUCT DataStruct; FLMBYTE * pszTemp = NULL; FLMBYTE * pszTemp1 = NULL; if( RC_BAD( rc = f_alloc( 150, &pszTemp))) { printErrorPage( rc, TRUE, (char *)"Failed to allocate temporary buffer"); goto Exit; } if( RC_BAD( rc = f_alloc( 150, &pszTemp1))) { printErrorPage( rc, TRUE, (char *)"Failed to allocate temporary buffer"); goto Exit; } // Initialize a few variables first... szFrom[0] = '\0'; szBucket[0] = '\0'; pFile = NULL; // Get the "From" parameter. We use this to determine everything else. if (RC_BAD( rc = ExtractParameter( uiNumParams, ppszParams, "From", sizeof( szFrom), szFrom))) { goto Exit; } f_mutexLock( gv_FlmSysData.hShareMutex); bFlmLocked = TRUE; if (!f_stricmp( szFrom, "FileHashTbl")) { // Get the hash bucket index if (RC_BAD( rc = ExtractParameter( uiNumParams, ppszParams, "Bucket", sizeof( szBucket), szBucket))) { goto Exit; } uiBucket = f_atoud( szBucket); pFile = (FFILE *)gv_FlmSysData.pFileHashTbl[uiBucket].pFirstInBucket; } else if ( (f_stricmp( szFrom, "SCacheBlock") == 0) || (f_stricmp( szFrom, "RCache") == 0) || (f_stricmp( szFrom, "FDB") == 0)) { // Get the FFile address and the Hash Bucket if (RC_BAD( rc = ExtractParameter( uiNumParams, ppszParams, "Bucket", sizeof( szBucket), szBucket))) { goto Exit; } uiBucket = f_atoud( szBucket); if (RC_BAD( rc = ExtractParameter( uiNumParams, ppszParams, "Address", sizeof( szAddress), szAddress))) { goto Exit; } pvAddress = (void *)f_atoud( szAddress); pFile = (FFILE *)gv_FlmSysData.pFileHashTbl[uiBucket].pFirstInBucket; while (pFile && (void *)pFile != pvAddress) { pFile = pFile->pNext; } } else if (f_stricmp( szFrom, "FlmSysData") == 0) { // Get the Link and the FFile address if (RC_BAD( rc = ExtractParameter( uiNumParams, ppszParams, "Link", sizeof( szLink), szLink))) { goto Exit; } if (RC_BAD( rc = ExtractParameter( uiNumParams, ppszParams, "Address", sizeof( szAddress), szAddress))) { goto Exit; } pvAddress = (void *)f_atoud( szAddress); if (f_stricmp( szLink, "pMrnuFile") == 0) { pFile = gv_FlmSysData.pMrnuFile; // Now let's make sure we are looking at the right FFile... while (pFile && (void *)pFile != pvAddress) { pFile = pFile->pNextNUFile; } } else if (f_stricmp( szLink, "pLrnuFile") == 0) { pFile = gv_FlmSysData.pLrnuFile; // Now let's make sure we are looking at the right FFile... while (pFile && (void *)pFile != pvAddress) { pFile = pFile->pPrevNUFile; } } } else if (f_stricmp( szFrom, "FFile") == 0) { // We need to get the Link, Bucket & Address if (RC_BAD(rc = ExtractParameter( uiNumParams, ppszParams, "Link", sizeof( szLink), szLink))) { goto Exit; } if (RC_BAD(rc = ExtractParameter( uiNumParams, ppszParams, "Address", sizeof( szAddress), szAddress))) { goto Exit; } pvAddress = (void *)f_atoud( szAddress); if (RC_BAD(rc = ExtractParameter( uiNumParams, ppszParams, "Bucket", sizeof( szBucket), szBucket))) { goto Exit; } uiBucket = f_atoud( szBucket); // First, let's get a reference to an FFile from the specified bucket if (gv_FlmSysData.pFileHashTbl[uiBucket].pFirstInBucket) { pFile = (FFILE *)gv_FlmSysData.pFileHashTbl[uiBucket].pFirstInBucket; } // Now let's make sure we are looking at the right FFile... while (pFile && (void *)pFile != pvAddress) { pFile = pFile->pNext; } // Now what link are we supposed to follow? if (f_stricmp( szLink, "pNext") == 0) { pFile = pFile->pNext; } else if (f_stricmp( szLink, "pPrev") == 0) { pFile = pFile->pPrev; } else if (f_stricmp( szLink, "pNextNUFile") == 0) { pFile = pFile->pNextNUFile; } else if (f_stricmp( szLink, "pPrevNUFile") == 0) { pFile = pFile->pPrevNUFile; } } // Gather additional data if present. Initialize the structure before // using it. f_memset( &DataStruct, 0, sizeof(DataStruct)); if (pFile) { f_memcpy( &localFFile, pFile, sizeof(localFFile)); if (pFile->pSCacheList) { DataStruct.SCacheBlkAddress = pFile->pSCacheList->uiBlkAddress; DataStruct.SCacheLowTransID = scaGetLowTransID( pFile->pSCacheList), DataStruct.SCacheHighTransID = pFile->pSCacheList->uiHighTransID; } if (pFile->pPendingWriteList) { DataStruct.PendingWriteBlkAddress = pFile->pPendingWriteList->uiBlkAddress; DataStruct.PendingWriteLowTransID = scaGetLowTransID( pFile->pPendingWriteList), DataStruct.PendingWriteHighTransID = pFile->pPendingWriteList->uiHighTransID; } if (pFile->pLastDirtyBlk) { DataStruct.LastDirtyBlkAddress = pFile->pLastDirtyBlk->uiBlkAddress; DataStruct.LastDirtyLowTransID = scaGetLowTransID( pFile->pLastDirtyBlk), DataStruct.LastDirtyHighTransID = pFile->pLastDirtyBlk->uiHighTransID; } if (pFile->pFirstRecord) { DataStruct.FirstRecordContainer = pFile->pFirstRecord->uiContainer; DataStruct.FirstRecordDrn = pFile->pFirstRecord->uiDrn; DataStruct.FirstRecordLowTransId = pFile->pFirstRecord->uiLowTransId; } if (pFile->pLastRecord) { DataStruct.LastRecordContainer = pFile->pLastRecord->uiContainer; DataStruct.LastRecordDrn = pFile->pLastRecord->uiDrn; DataStruct.LastRecordLowTransId = pFile->pLastRecord->uiLowTransId; } } f_mutexUnlock( gv_FlmSysData.hShareMutex); bFlmLocked = FALSE; stdHdr(); fnPrintf( m_pHRequest, HTML_DOCTYPE); fnPrintf( m_pHRequest, "<html>\n"); // Determine if we are being requested to refresh this page or not. if ((bRefresh = DetectParameter( uiNumParams, ppszParams, "Refresh")) == TRUE) { // Send back the page with a refresh command in the header f_sprintf( (char *)pszTemp, "%s/FFile?Refresh&From=%s&Bucket=%s", m_pszURLString, szFrom, szBucket); fnPrintf( m_pHRequest, "<HEAD>" "<META http-equiv=\"refresh\" content=\"5; url=%s\">" "<TITLE>FFile Structure</TITLE>\n", pszTemp); } else { fnPrintf( m_pHRequest, "<HEAD><TITLE>FFile Structure</TITLE>\n"); } printStyle(); fnPrintf( m_pHRequest, "</HEAD>\n"); fnPrintf( m_pHRequest, "<body>\n"); // If we are not to refresh this page, then don't include the // refresh meta command if (!bRefresh) { f_sprintf( (char *)pszTemp, "<A HREF=%s/FFile?Refresh&From=%s&Bucket=%s>Start Auto-refresh (5 sec.)</A>", m_pszURLString, szFrom, szBucket); } else { f_sprintf( (char *)pszTemp, "<A HREF=%s/FFile?From=%s&Bucket=%s>Stop Auto-refresh</A>", m_pszURLString, szFrom, szBucket); } // Prepare the refresh link. f_sprintf( (char *)pszTemp1, "<A HREF=%s/FFile?From=%s&Bucket=%s>Refresh</A>", m_pszURLString, szFrom, szBucket); // Show the table headings and the refresh option. if (pFile) { // Write out the table headings printTableStart( "FFile Structure", 4, 100); printTableRowStart(); printColumnHeading( "", JUSTIFY_LEFT, FLM_IMON_COLOR_PUTTY_1, 4, 1, FALSE); fnPrintf( m_pHRequest, "%s, ", pszTemp1); fnPrintf( m_pHRequest, "%s\n", pszTemp); printColumnHeadingClose(); printTableRowEnd(); // Write out the table headings. printTableRowStart(); printColumnHeading( "Byte Offset (hex)"); printColumnHeading( "Field Name"); printColumnHeading( "Field Type"); printColumnHeading( "Value"); printTableRowEnd(); write_data( (pFile ? &localFFile: NULL), (void *)pFile, &DataStruct); } else { // Write out an error page... fnPrintf( m_pHRequest, "<P>Unable to find the FFile structure that you requested." " This is probably because the state of the cache changed between " "the time that you displayed the previous page and the time that you " "clicked on the link that brought you here.\n" "<P>Click on your browser's \"Back\" button, then click \"Reload\" " "and then try the link again.\n"); } fnPrintf( m_pHRequest, "</body></html>\n"); fnEmit(); Exit: if (bFlmLocked) { f_mutexUnlock( gv_FlmSysData.hShareMutex); bFlmLocked = FALSE; } if (pszTemp) { f_free( &pszTemp); } if (pszTemp1) { f_free( &pszTemp1); } return( rc); }