Пример #1
0
/****************************************************************************
Desc:	Close the database file and delete it.
****************************************************************************/
RCODE F_DbCheck::closeAndDeleteResultSetDb( void)
{
	RCODE				rc = NE_XFLM_OK;
	
	if (m_pResultSetDb)
	{
		if (m_pResultSetDb->getTransType() != XFLM_NO_TRANS)
		{
			m_pResultSetDb->transAbort();
		}
		m_pResultSetDb->Release();
		m_pResultSetDb = NULL;
	}

	if (RC_BAD( rc = gv_pXFlmDbSystem->dbRemove( 
		m_szResultSetDibName, NULL, NULL, TRUE)))
	{
		goto Exit;
	}

	f_memset( m_szResultSetDibName, 0, sizeof( m_szResultSetDibName));

Exit:

	return rc;
}
Пример #2
0
/****************************************************************************
Desc:
****************************************************************************/
RCODE TestBase::openTestState(
	const char *		pszDibName)
{
	RCODE					rc = FERR_OK;
	CREATE_OPTS			createOpts;

	if( RC_BAD( rc = gv_FlmSysData.pFileSystem->doesFileExist( pszDibName)))
	{
		// Create the database

		f_memset( &createOpts, 0, sizeof( CREATE_OPTS));
		
		if( RC_BAD( rc = FlmDbCreate( pszDibName, 
			NULL, NULL, NULL, NULL, &createOpts, &m_hDb)))
		{
			goto Exit;
		}
	}
	else
	{
		// Open the existing database

		if( RC_BAD( rc = FlmDbOpen( pszDibName, NULL, NULL, 
			0, NULL, &m_hDb)))
		{
			goto Exit;
		}
	}

Exit:

	return( rc);
}
Пример #3
0
/****************************************************************************
Desc:
****************************************************************************/
void FlagSet::init( 
	FLMBYTE **		ppucElemArray,
	FLMUINT			uiNumElems)
{
	reset();
	
	if( RC_BAD( f_alloc( sizeof( FLMBYTE *) * uiNumElems,
										&m_ppucElemArray)))
	{
		flmAssert( 0);
	}
	
	if( RC_BAD( f_alloc( sizeof( FLMBOOL) * uiNumElems,
										&m_pbFlagArray)))
	{
		flmAssert( 0);
	}
	
	f_memset( m_pbFlagArray, 0, sizeof( FLMBOOL) * uiNumElems);
	
	for( FLMUINT uiLoop = 0; uiLoop < uiNumElems; uiLoop++)
	{
		if( RC_BAD( f_alloc( f_strlen( (char *)ppucElemArray[ uiLoop]) + 1,
				&m_ppucElemArray[ uiLoop])))
		{
			flmAssert( 0);
		}
		
		f_strcpy( (char *)m_ppucElemArray[uiLoop], (char *)ppucElemArray[uiLoop]);
	}
	
	m_uiNumElems = uiNumElems;
}
Пример #4
0
/****************************************************************************
Desc:
****************************************************************************/
RCODE TestBase::initCleanTestState( 
	const char * 	pszDibName)
{
	RCODE				rc = FERR_OK;
	CREATE_OPTS		createOpts;

	// Create the database
	
	f_memset( &createOpts, 0, sizeof( CREATE_OPTS));
	
	if ( RC_BAD( rc = FlmDbCreate( pszDibName, 
		NULL, NULL, NULL, NULL, &createOpts, &m_hDb)))
	{
		if( rc == FERR_FILE_EXISTS)
		{
			if( RC_BAD( rc = FlmDbRemove( pszDibName,
				NULL, NULL, TRUE)))
			{
				goto Exit;
			}
		}

		if( RC_BAD( rc = FlmDbCreate( pszDibName, 
			NULL, NULL, NULL, NULL, &createOpts, &m_hDb)))
		{
			goto Exit;
		}
	}

Exit:

	return( rc);
}
Пример #5
0
/****************************************************************************
Desc:
****************************************************************************/
FlagSet::FlagSet( 
	const FlagSet&		fs)
{
	if( RC_BAD( f_alloc( sizeof( FLMBYTE *) * fs.m_uiNumElems,
										&m_ppucElemArray)))
	{
		flmAssert( 0);
	}
	
	if( RC_BAD( f_alloc( sizeof( FLMBOOL) * fs.m_uiNumElems,
										&m_pbFlagArray)))
	{
		flmAssert( 0);
	}
	
	f_memset( m_pbFlagArray, 0, sizeof( FLMBOOL) * fs.m_uiNumElems);
	
	for( FLMUINT uiLoop = 0; uiLoop < fs.m_uiNumElems; uiLoop++)
	{
		if( RC_BAD( f_alloc( f_strlen( (char *)fs.m_ppucElemArray[uiLoop]) + 1,
				&m_ppucElemArray[ uiLoop])))
		{
			flmAssert( 0);
		}
		
		f_strcpy( (char *)m_ppucElemArray[uiLoop], 
					 (char *)fs.m_ppucElemArray[uiLoop]);
	}
	
	m_uiNumElems = fs.m_uiNumElems;
}
Пример #6
0
RCODE FTKAPI F_DirHdl::openDir(
	const char *	pszDirName,
	const char *	pszPattern)
{
	RCODE		rc = NE_FLM_OK;

	m_rc = NE_FLM_OK;
	m_bFirstTime = TRUE;
	m_bFindOpen = FALSE;
	m_uiAttrib = 0;

	f_memset( &m_FindData, 0, sizeof( m_FindData));
	f_strcpy( m_szDirectoryPath, pszDirName);

	if( pszPattern)
	{
		if( f_strlen( pszPattern) >= (FLMINT)sizeof( m_szPattern))
		{
			rc = RC_SET( NE_FLM_MEM);
			goto Exit;
		}

		f_strcpy( m_szPattern, pszPattern);
	}
	else
	{
		m_szPattern[ 0] = 0;
	}

Exit:

	return( rc);
}
Пример #7
0
/********************************************************************
Desc: Output a label in the LABEL_COLUMN
*********************************************************************/
void gigaOutputLabel(
	FLMUINT			uiRow,
	const char *	pszLabel,
	FLMBOOL			bMutexLocked)
{
	char			szLabel [DATA_COLUMN - LABEL_COLUMN];
	char *		pszTmp;
	FLMUINT		uiNumDots = sizeof( szLabel) - 1;

	f_memset( szLabel, '.', uiNumDots);
	szLabel [uiNumDots] = 0;

	pszTmp = &szLabel [0];
	uiNumDots -= 2;
	
	while( *pszLabel && uiNumDots)
	{
		*pszTmp++ = (FLMBYTE)(*pszLabel++);
		uiNumDots--;
	}
	
	if( !bMutexLocked && gv_hWindowMutex != F_MUTEX_NULL)
	{
		f_mutexLock( gv_hWindowMutex);
	}
	
	FTXWinPrintStrXY( gv_pWindow, szLabel, LABEL_COLUMN, uiRow);
	
	if( !bMutexLocked && gv_hWindowMutex != F_MUTEX_NULL)
	{
		f_mutexUnlock( gv_hWindowMutex);
	}

}
Пример #8
0
	FINLINE FLMINT FTKAPI outputChar(
		char				cChar,
		FLMUINT			uiCount)
	{
		f_memset( m_pszDestBuffer, cChar, uiCount);
		m_pszDestBuffer += uiCount;
		
		return( (FLMINT)uiCount);
	}
Пример #9
0
/****************************************************************************
Desc:	Make sure the vector array is allocated at least up to the element
		number that is passed in.
****************************************************************************/
RCODE F_DataVector::allocVectorArray(
	FLMUINT	uiElementNumber)
{
	RCODE	rc = NE_XFLM_OK;

	if (uiElementNumber >= m_uiNumElements)
	{

		// May need to allocate a new vector array

		if (uiElementNumber >= m_uiVectorArraySize)
		{
			FLMUINT					uiNewArraySize = uiElementNumber + 32;
			F_VECTOR_ELEMENT *	pNewVector;

			if (m_pVectorElements == &m_VectorArray [0])
			{
				if (RC_BAD( rc = f_alloc( uiNewArraySize * sizeof( F_VECTOR_ELEMENT),
											&pNewVector)))
				{
					goto Exit;
				}
				if (m_uiNumElements)
				{
					f_memcpy( pNewVector, m_pVectorElements,
						m_uiNumElements * sizeof( F_VECTOR_ELEMENT));
				}
			}
			else
			{
				pNewVector = m_pVectorElements;

				if (RC_BAD( rc = f_realloc( uiNewArraySize * sizeof( F_VECTOR_ELEMENT),
											&pNewVector)))
				{
					goto Exit;
				}

			}
			m_pVectorElements = pNewVector;
			m_uiVectorArraySize = uiNewArraySize;
		}

		// Initialized everything between the old last element and
		// the new element, including the new element, to zeroes.

		f_memset( &m_pVectorElements [m_uiNumElements], 0,
			sizeof( F_VECTOR_ELEMENT) *
			(uiElementNumber - m_uiNumElements + 1));

		m_uiNumElements = uiElementNumber + 1;
	}

Exit:

	return( rc);
}
Пример #10
0
/****************************************************************************
Desc:
****************************************************************************/
RCODE	SortKeyTestImpl::createNameDoc( 
	char *		pszNames[ 2])
{
	RCODE						rc = NE_XFLM_OK;
	ELEMENT_NODE_INFO 	pNameNodes[2];

	f_memset( pNameNodes, 0, sizeof( pNameNodes));

	if ( RC_BAD( rc = f_alloc( 
		f_strlen( pszNames[0]) + 1, &pNameNodes[0].pvData)))
	{
		MAKE_FLM_ERROR_STRING( "f_alloc failed.", m_szDetails, rc);
		goto Exit;
	}

	f_strcpy( (char*)pNameNodes[0].pvData, pszNames[0]);
	pNameNodes[0].uiDataType = XFLM_TEXT_TYPE;
	pNameNodes[0].uiDataSize = f_strlen( pszNames[0]);
	pNameNodes[0].uiDictNum = FIRST_NAME_ID;

	if ( RC_BAD( rc = f_alloc( 
		f_strlen( pszNames[1]) + 1, &pNameNodes[1].pvData)))
	{
		MAKE_FLM_ERROR_STRING( "f_alloc failed.", m_szDetails, rc);
		goto Exit;
	}

	f_strcpy( (char*)pNameNodes[1].pvData, pszNames[1]);
	pNameNodes[1].uiDataType = XFLM_TEXT_TYPE;
	pNameNodes[1].uiDataSize = f_strlen( pszNames[0]);
	pNameNodes[1].uiDictNum = LAST_NAME_ID;

	if ( RC_BAD( rc = createCompoundDoc( pNameNodes, 2, NULL)))
	{
		goto Exit;
	}

Exit:

	if ( pNameNodes[0].pvData)
	{
		f_free( &pNameNodes[0].pvData);
	}

	if ( pNameNodes[1].pvData)
	{
		f_free( &pNameNodes[1].pvData);
	}

	return rc;
}
Пример #11
0
/****************************************************************************
Desc:
****************************************************************************/
F_MultiFileHdl::F_MultiFileHdl(
	FLMUINT			uiMaxFileSize)
{
	m_bOpen = FALSE;
	m_szPath[ 0] = 0;
	m_ui64EOF = 0;
	m_pLockFileHdl = NULL;
	f_memset( m_pFileHdlList, 0, sizeof( FH_INFO) * F_MULTI_FHDL_LIST_SIZE);
	m_uiMaxFileSize = uiMaxFileSize;
	
	if( !m_uiMaxFileSize)
	{
		m_uiMaxFileSize = F_MULTI_FHDL_DEFAULT_MAX_FILE_SIZE;
	}
}
Пример #12
0
/****************************************************************************
Desc:
****************************************************************************/
RCODE F_DbCheck::createAndOpenResultSetDb( void)
{
	RCODE					rc = NE_XFLM_OK;
	XFLM_CREATE_OPTS	createOpts;

	if (m_pResultSetDb)
	{
		if (RC_BAD( rc = closeAndDeleteResultSetDb()))
		{
			goto Exit;
		}
	}

	f_memset( &createOpts, 0, sizeof( XFLM_CREATE_OPTS));
	for (;;)
	{

		// Generate a random file name
		
		f_sprintf( m_szResultSetDibName,
					  "%d.db", (int)m_pRandGen->getUINT32( 100, 20000));
		
		if (RC_OK( rc = gv_pXFlmDbSystem->dbCreate( 
				m_szResultSetDibName, NULL, NULL, NULL, NULL, 
				&createOpts, TRUE, (IF_Db **)&m_pResultSetDb)))
		{
			break;
		}
		if (rc == NE_XFLM_FILE_EXISTS || rc == NE_FLM_IO_ACCESS_DENIED)
		{
			rc = NE_XFLM_OK;
		}
		else
		{
			goto Exit;
		}
	}

	// Shouldn't have an RFL object - don't want anything
	// logged by this database.
	
	flmAssert( !m_pResultSetDb->getDatabase()->m_pRfl);

Exit:

	return rc;
}
Пример #13
0
/********************************************************************
Desc: ?
*********************************************************************/
FSTATIC void bldOutLabel(
	FLMUINT			uiCol,
	FLMUINT			uiRow,
	const char *	pucLabel,
	const char *	pucValue,
	FLMUINT			uiNumValue,
	FLMBOOL			bLogIt)
{
	char			szMsg[ 100];
	FLMUINT		uiLen = (FLMUINT)(VALUE_COLUMN - uiCol - 1);

	f_memset( szMsg, '.', uiLen);
	szMsg[ uiLen] = 0;
	f_conSetBackFore( FLM_BLACK, FLM_LIGHTGRAY);
	f_conStrOutXY( szMsg, uiCol, uiRow);
	f_conStrOutXY( pucLabel, uiCol, uiRow);

	if( pucValue != NULL)
	{
		bldOutValue( uiRow, pucValue);
	}
	else
	{
		bldOutNumValue( uiRow, uiNumValue);
	}

	if( (bLogIt) && (gv_bLoggingEnabled))
	{
		f_strcpy( szMsg, pucLabel);
		f_strcpy( &szMsg[ f_strlen( szMsg)], ": ");
		if( pucValue != NULL)
		{
			f_strcpy( &szMsg[ f_strlen( szMsg)], pucValue);
		}
		else
		{
			f_sprintf( (char *)(&szMsg[ f_strlen( szMsg)]), "%u",
				(unsigned)uiNumValue);
		}
		bldLogString( szMsg);
	}
}
Пример #14
0
/********************************************************************
Desc: This routine initializes a XFLM_DB_HDR structure.
*********************************************************************/
void flmInitDbHdr(
	XFLM_CREATE_OPTS *	pCreateOpts,
	FLMBOOL					bCreatingDatabase,
	FLMBOOL					bTempDb,
	XFLM_DB_HDR *			pDbHdr)
{
	FLMUINT	uiMinRflFileSize;
	FLMUINT	uiMaxRflFileSize;

	if (bCreatingDatabase)
	{
		f_memset( pDbHdr, 0, sizeof( XFLM_DB_HDR));
	}

	// If pCreateOpts is non-NULL, copy it into the file header.

	f_strcpy( (char *)pDbHdr->szSignature, XFLM_DB_SIGNATURE);
	pDbHdr->ui8IsLittleEndian = XFLM_NATIVE_IS_LITTLE_ENDIAN;

	if (pCreateOpts)
	{
		pDbHdr->ui16BlockSize = (FLMUINT16)pCreateOpts->ui32BlockSize;
		pDbHdr->ui8DefaultLanguage = (FLMUINT8)pCreateOpts->ui32DefaultLanguage;
		if (pCreateOpts->bKeepRflFiles)
		{
			pDbHdr->ui8RflKeepFiles = 1;
		}
		if (pCreateOpts->bLogAbortedTransToRfl)
		{
			pDbHdr->ui8RflKeepAbortedTrans = 1;
		}

		if( (uiMinRflFileSize = (FLMUINT)pCreateOpts->ui32MinRflFileSize) == 0)
		{
			uiMinRflFileSize = XFLM_DEFAULT_MIN_RFL_FILE_SIZE;
		}

		if( (uiMaxRflFileSize = (FLMUINT)pCreateOpts->ui32MaxRflFileSize) == 0)
		{
			uiMaxRflFileSize = XFLM_DEFAULT_MAX_RFL_FILE_SIZE;
		}
	}
	else
	{

		// If pCreateOpts is NULL, initialize some default values.

		pDbHdr->ui16BlockSize = XFLM_DEFAULT_BLKSIZ;
		pDbHdr->ui8DefaultLanguage = XFLM_DEFAULT_LANG;
		uiMinRflFileSize = XFLM_DEFAULT_MIN_RFL_FILE_SIZE;
		uiMaxRflFileSize = XFLM_DEFAULT_MAX_RFL_FILE_SIZE;
	}

	// Make sure the RFL size limits are valid.
	// Maximum must be enough to hold at least one packet plus
	// the RFL header.  Minimum must not be greater than the
	// maximum.  NOTE: Minimum and maximum are allowed to be
	// equal, but in all cases, maximum takes precedence over
	// minimum.  We will first NOT exceed the maximum.  Then,
	// if possible, we will go above the minimum.

	if (uiMaxRflFileSize < RFL_MAX_PACKET_SIZE + 512)
	{
		uiMaxRflFileSize = RFL_MAX_PACKET_SIZE + 512;
	}
	if (uiMaxRflFileSize > gv_XFlmSysData.uiMaxFileSize)
	{
		uiMaxRflFileSize = gv_XFlmSysData.uiMaxFileSize;
	}
	if (uiMinRflFileSize > uiMaxRflFileSize)
	{
		uiMinRflFileSize = uiMaxRflFileSize;
	}
	pDbHdr->ui32RflMinFileSize = (FLMUINT32)uiMinRflFileSize;
	pDbHdr->ui32RflMaxFileSize = (FLMUINT32)uiMaxRflFileSize;

	// Only allow database to be created with current version number

	pDbHdr->ui32DbVersion = XFLM_CURRENT_VERSION_NUM;
	pDbHdr->ui8BlkChkSummingEnabled = 1;

	// Round block size up to nearest legal block size.

	pDbHdr->ui16BlockSize =
		(FLMUINT16)flmAdjustBlkSize( (FLMUINT)pDbHdr->ui16BlockSize);

	if (!bTempDb)
	{
		pDbHdr->ui32FirstLFBlkAddr = (FLMUINT32)FSBlkAddress(1, 0);
	}

	// If creating a database, initialize some more items.

	if (bCreatingDatabase)
	{

		// Set the logical EOF.

		if (!bTempDb)
		{
			pDbHdr->ui32LogicalEOF = pDbHdr->ui32FirstLFBlkAddr +
											(FLMUINT32)pDbHdr->ui16BlockSize;
		}
		else
		{
			pDbHdr->ui32LogicalEOF = (FLMUINT32)FSBlkAddress(1, 0);
		}
		pDbHdr->ui64CurrTransID = (FLMUINT64)0;
		pDbHdr->ui32RflCurrFileNum = 1;

		// Putting a zero in this value tells the RFL code that the
		// RFL file should be created - overwriting it if it already
		// exists.

		pDbHdr->ui32RflLastCPFileNum = 1;
		pDbHdr->ui32RflLastCPOffset = 512;
		pDbHdr->ui32RblEOF = pDbHdr->ui16BlockSize;

		// Set the database serial number

		f_createSerialNumber( pDbHdr->ucDbSerialNum);

		// Set the "current" RFL serial number - will be stamped into the RFL
		// file when it is first created.

		f_createSerialNumber( pDbHdr->ucLastTransRflSerialNum);

		// Set the "next" RFL serial number

		f_createSerialNumber( pDbHdr->ucNextRflSerialNum);

		// Set the incremental backup serial number and sequence number

		f_createSerialNumber( pDbHdr->ucIncBackupSerialNum);
		pDbHdr->ui32IncBackupSeqNum = 1;

		// Set the file size limits

		pDbHdr->ui32MaxFileSize = (FLMUINT32)gv_XFlmSysData.uiMaxFileSize;

		// Need at least two blocks to create a database!

		flmAssert( (FLMUINT)pDbHdr->ui32MaxFileSize >=
					  (FLMUINT)pDbHdr->ui16BlockSize * 2);
	}
}
Пример #15
0
/****************************************************************************
Desc: Returns the requested file handle
****************************************************************************/
RCODE F_MultiFileHdl::getFileHdl(
	FLMUINT				uiFileNum,
	FLMBOOL				bGetForWrite,
	IF_FileHdl **		ppFileHdl)
{
	RCODE					rc	= NE_FLM_OK;
	IF_FileSystem *	pFileSystem = f_getFileSysPtr();
	FLMUINT				uiSlot;
	IF_FileHdl *		pTmpHdl;
	char					szPath[ F_PATH_MAX_SIZE];

	f_assert( m_bOpen);

	*ppFileHdl = NULL;

	uiSlot = uiFileNum % F_MULTI_FHDL_LIST_SIZE;
	pTmpHdl = m_pFileHdlList[ uiSlot].pFileHdl;

	if( pTmpHdl && m_pFileHdlList[ uiSlot].uiFileNum != uiFileNum)
	{
		if( RC_BAD( rc = pTmpHdl->flush()))
		{
			goto Exit;
		}

		pTmpHdl->closeFile();
		pTmpHdl->Release();
		pTmpHdl = NULL;

		f_memset( &m_pFileHdlList[ uiSlot], 0, sizeof( FH_INFO));
	}

	if( !pTmpHdl)
	{
		dataFilePath( uiFileNum, szPath);
		if( RC_BAD( rc = pFileSystem->openFile( szPath, 
			FLM_IO_RDWR, &pTmpHdl)))
		{
			if( rc == NE_FLM_IO_PATH_NOT_FOUND && bGetForWrite)
			{
				if( RC_BAD( rc = pFileSystem->createFile( szPath,
 					FLM_IO_RDWR, &pTmpHdl)))
				{
					goto Exit;
				}
			}
			else
			{
				goto Exit;
			}
		}

		m_pFileHdlList[ uiSlot].pFileHdl = pTmpHdl;
		m_pFileHdlList[ uiSlot].uiFileNum = uiFileNum;
		f_assert( !m_pFileHdlList[ uiSlot].bDirty);
	}

	*ppFileHdl = m_pFileHdlList[ uiSlot].pFileHdl;
	if( bGetForWrite)
	{
		m_pFileHdlList[ uiSlot].bDirty = TRUE;
	}

Exit:

	return( rc);
}
Пример #16
0
/****************************************************************************
Desc: Retrieves the Checkpoint info for the database passed in.  This assumes
		global mutex has already been locked.
*****************************************************************************/
void F_Database::getCPInfo(
	XFLM_CHECKPOINT_INFO *		pCheckpointInfo)
{
	FLMUINT	uiElapTime;
	FLMUINT	uiCurrTime;

	flmAssert( pCheckpointInfo);

	f_memset( pCheckpointInfo, 0, sizeof( XFLM_CHECKPOINT_INFO));
	if (m_pCPInfo)
	{
		pCheckpointInfo->bRunning = m_pCPInfo->bDoingCheckpoint;
		if (pCheckpointInfo->bRunning)
		{
			if (m_pCPInfo->uiStartTime)
			{
				uiCurrTime = FLM_GET_TIMER();

				uiElapTime = FLM_ELAPSED_TIME( uiCurrTime,
							m_pCPInfo->uiStartTime);
				pCheckpointInfo->ui32RunningTime = (FLMUINT32)FLM_TIMER_UNITS_TO_MILLI( uiElapTime);
			}
			else
			{
				pCheckpointInfo->ui32RunningTime = 0;
			}
			pCheckpointInfo->bForcingCheckpoint =
				m_pCPInfo->bForcingCheckpoint;
			if (m_pCPInfo->uiForceCheckpointStartTime)
			{
				uiCurrTime = FLM_GET_TIMER();
				uiElapTime = FLM_ELAPSED_TIME( uiCurrTime,
							m_pCPInfo->uiForceCheckpointStartTime);
				pCheckpointInfo->ui32ForceCheckpointRunningTime = 
					(FLMUINT32)FLM_TIMER_UNITS_TO_MILLI( uiElapTime);
			}
			else
			{
				pCheckpointInfo->ui32ForceCheckpointRunningTime = 0;
			}
			pCheckpointInfo->ui32ForceCheckpointReason =
				(FLMUINT32)m_pCPInfo->iForceCheckpointReason;
			pCheckpointInfo->bWritingDataBlocks =
				m_pCPInfo->bWritingDataBlocks;
			pCheckpointInfo->ui32LogBlocksWritten =
				(FLMUINT32)m_pCPInfo->uiLogBlocksWritten;
			pCheckpointInfo->ui32DataBlocksWritten =
				(FLMUINT32)m_pCPInfo->uiDataBlocksWritten;
		}
		pCheckpointInfo->ui32BlockSize = (FLMUINT32)m_uiBlockSize;
		pCheckpointInfo->ui32DirtyCacheBytes =
			(FLMUINT32)(m_uiDirtyCacheCount * m_uiBlockSize);
		if (m_pCPInfo->uiStartWaitTruncateTime)
		{
			uiCurrTime = FLM_GET_TIMER();

			uiElapTime = FLM_ELAPSED_TIME( uiCurrTime,
						m_pCPInfo->uiStartWaitTruncateTime);
			pCheckpointInfo->ui32WaitTruncateTime = 
				(FLMUINT32)FLM_TIMER_UNITS_TO_MILLI( uiElapTime);
		}
		else
		{
			pCheckpointInfo->ui32WaitTruncateTime = 0;
		}
	}
}
Пример #17
0
/***************************************************************************
Desc:	This routine reads and verifies the information contained in the
		file header and log header of a FLAIM database.
*****************************************************************************/
RCODE flmReadAndVerifyHdrInfo(
	XFLM_DB_STATS *	pDbStats,
	IF_FileHdl *		pFileHdl,
	XFLM_DB_HDR *		pDbHdr,
	FLMUINT32 *			pui32CalcCRC)
{
	RCODE		rc = NE_XFLM_OK;
	FLMUINT	uiBytesRead;

	// Read the database header.

	f_memset( pDbHdr, 0, sizeof( XFLM_DB_HDR));
	if (RC_BAD( rc = pFileHdl->read( (FLMUINT)0, sizeof( XFLM_DB_HDR),
									pDbHdr, &uiBytesRead)))
	{
		if (rc != NE_FLM_IO_END_OF_FILE)
		{
			if (pDbStats)
			{
				pDbStats->uiReadErrors++;
			}
		}
		else
		{
			if (pui32CalcCRC)
			{
				*pui32CalcCRC = calcDbHdrCRC( pDbHdr);
			}

			// Get what we can out of the header.

			if (hdrIsNonNativeFormat( pDbHdr))
			{
				convertDbHdr( pDbHdr);
			}
		}
		goto Exit;
	}

	if (pui32CalcCRC)
	{
		*pui32CalcCRC = calcDbHdrCRC( pDbHdr);
	}
	if (uiBytesRead < sizeof( XFLM_DB_HDR))
	{

		// Still get what we can out of the header.

		if (hdrIsNonNativeFormat( pDbHdr))
		{
			convertDbHdr( pDbHdr);
		}
		rc = RC_SET( NE_XFLM_NOT_FLAIM);
		goto Exit;
	}
	else
	{

		// This routine will convert to native format if it is not
		// in native format.

		if (RC_BAD( rc = verifyDbHdr( pDbHdr)))
		{
			goto Exit;
		}
	}

Exit:

	return( rc);
}
Пример #18
0
/****************************************************************************
Desc: Constructor for F_Database object.
****************************************************************************/
F_Database::F_Database(
	FLMBOOL	bTempDb)
{
	m_krefPool.poolInit( DEFAULT_KREF_POOL_BLOCK_SIZE * 8);
	m_pNext = NULL;
	m_pPrev = NULL;
	m_pFirstQuery = NULL;
	m_pLastQuery = NULL;
	m_uiBlockSize = 0;
	m_uiDefaultLanguage = 0;
	m_uiMaxFileSize = 0;
	m_uiOpenIFDbCount = 0;
	m_bTempDb = bTempDb;
	m_pFirstDb = NULL;
	m_pszDbPath = NULL;
	m_pszDataDir = NULL;
	m_pSCacheList = NULL;
	m_pFirstNode = NULL;
	m_pLastNode = NULL;
	m_pLastDirtyNode = NULL;
	m_pPendingWriteList = NULL;
	m_pLastDirtyBlk = NULL;
	m_pFirstInLogList = NULL;
	m_pLastInLogList = NULL;
	m_uiLogListCount = 0;
	m_pFirstInNewList = NULL;
	m_pLastInNewList = NULL;
	m_uiNewCount = 0;
	m_uiDirtyCacheCount = 0;
	m_uiLogCacheCount = 0;
	m_ppBlocksDone = NULL;
	m_uiBlocksDoneArraySize = 0;
	m_uiBlocksDone = 0;
	m_pTransLogList = NULL;
	m_pOpenNotifies = NULL;
	m_pCloseNotifies = NULL;
	m_pDictList = NULL;
	m_bMustClose = FALSE;
	m_rcMustClose = NE_XFLM_OK;
	m_uiSigBitsInBlkSize = 0;
	if (!bTempDb)
	{
		m_uiFileExtendSize = XFLM_DEFAULT_FILE_EXTEND_SIZE;
	}
	else
	{
		m_uiFileExtendSize = 65536;
	}
	
	m_pRfl = NULL;
	
	f_memset( &m_lastCommittedDbHdr, 0, sizeof( m_lastCommittedDbHdr));
	f_memset( &m_checkpointDbHdr, 0, sizeof( m_checkpointDbHdr));
	f_memset( &m_uncommittedDbHdr, 0, sizeof( m_uncommittedDbHdr));

	m_pBufferMgr = NULL;
	m_pCurrLogBuffer = NULL;
	m_uiCurrLogWriteOffset = 0;
	m_uiCurrLogBlkAddr = 0;
	m_pDbHdrWriteBuf = NULL;
	m_pucUpdBuffer = NULL;
	m_uiUpdBufferSize = 0;
	m_uiUpdByteCount = 0;
	m_uiUpdCharCount = 0;
	m_uiPendingType = XFLM_NODATA_TYPE;
	m_pPendingInput = NULL;
	m_pPendingBTree = NULL;
	m_pucBTreeTmpBlk = NULL;
	m_pucBTreeTmpDefragBlk = NULL;
	m_pucEntryArray = NULL;
	m_pucSortedArray = NULL;
	m_pucBtreeBuffer = NULL;
	m_pucReplaceStruct = NULL;
	m_pDatabaseLockObj = NULL;
	m_pWriteLockObj = NULL;
	m_pLockFileHdl = NULL;
	m_pLockNotifies = NULL;
	m_bBeingLocked = FALSE;
	m_pFirstReadTrans = NULL;
	m_pLastReadTrans = NULL;
	m_pFirstKilledTrans = NULL;
	m_uiFirstLogBlkAddress = 0;
	m_uiFirstLogCPBlkAddress = 0;
	m_uiLastCheckpointTime = 0;
	m_pCPThrd = NULL;
	m_pCPInfo = NULL;
	m_CheckpointRc = NE_XFLM_OK;
	m_uiBucket = 0;
	m_uiFlags = 0;
	m_bBackupActive = FALSE;
	m_pMaintThrd = NULL;
	m_hMaintSem = F_SEM_NULL;
	m_bAllowLimitedMode = FALSE;
	m_bInLimitedMode = FALSE;
	m_pszDbPasswd = NULL;
	m_pWrappingKey = NULL;
	m_bHaveEncKey = FALSE;
	m_rcLimitedCode = NE_XFLM_OK;
	m_hMutex = F_MUTEX_NULL;
}
Пример #19
0
RCODE f_fileFindFirst(
	char *				pszSearchPath,
   FLMUINT				uiSearchAttrib,
	F_IO_FIND_DATA	*	pFindData,
   char *				pszFoundPath,
	FLMUINT *			puiFoundAttrib)
{
	RCODE					rc = NE_FLM_OK;
	char 					szTmpPath[ F_PATH_MAX_SIZE];
	FSTATIC char		pszWildCard[] = {'*',0};
	int					iRetVal;
	IF_FileSystem *	pFileSystem = f_getFileSysPtr();

	if( !pszSearchPath)
	{
		rc = RC_SET( NE_FLM_IO_PATH_NOT_FOUND);
		goto Exit;
	}

	f_strcpy( szTmpPath, pszSearchPath);
	if( RC_BAD( rc = pFileSystem->pathAppend( szTmpPath, pszWildCard)))
	{
		goto Exit;
	}

	f_memset( pFindData, 0, sizeof( F_IO_FIND_DATA));
	if( uiSearchAttrib & F_IO_FA_DIRECTORY)
	{
		pFindData->mode_flag |= S_IFDIR;
	}

	if( uiSearchAttrib & F_IO_FA_RDONLY)
	{
		pFindData->mode_flag |= S_IREAD;
	}

	iRetVal = Find1( (char*)szTmpPath, pFindData);

	if( iRetVal != 0)
	{
		// If there were no more files found then return no more files
		// instead of mapping to error path not found or io error.
		// To return no more files ret_val is ENOENT (set in Find2)
		// and errno is not set

		if( iRetVal == ENOENT && errno == 0)
		{
			rc = RC_SET( NE_FLM_IO_NO_MORE_FILES);
		}
		else
		{
			rc = f_mapPlatformError( errno, NE_FLM_READING_FILE);
		}
		
		goto Exit;
	}

	// filter out ".." (PARENT) and "." (CURRENT) directories
	
	if( uiSearchAttrib & F_IO_FA_DIRECTORY )
	{
		while( (f_strcmp( pFindData->name, "..") == 0) ||
			   (f_strcmp( pFindData->name, ".") == 0))
		{
			if( (iRetVal = Find2( pFindData)) != 0)
			{
				// If there were no more files found then return no more files
				// instead of mapping to error path not found or io error.
				// To return no more files ret_val is ENOENT (set in Find2)
				// and errno is not set
				
				if( iRetVal == ENOENT && errno == 0)
				{
					rc = RC_SET( NE_FLM_IO_NO_MORE_FILES);
				}
				else
				{
					rc = f_mapPlatformError( errno, NE_FLM_READING_FILE);
				}
				
				goto Exit;
			}
		}
	}

	// Append the file name to the path name
	
	f_strcpy( pszFoundPath, pszSearchPath);
	
	if( RC_BAD( rc = pFileSystem->pathAppend( pszFoundPath, 
		(char *)pFindData->name)))
	{
		goto Exit;
	}

	*puiFoundAttrib = (FLMUINT)ReturnAttributes(
			pFindData->FileStat.st_mode, pszFoundPath);

	// Save the search path in the NE_FLM_IO_FIND_DATA struct
	// for a find next call

	f_strcpy( pFindData->search_path, pszSearchPath);

Exit:

	return( rc);
}
Пример #20
0
/***************************************************************************
Desc: This routine begins a thread that will do checkpoints for the
		passed in database.  It gives the thread its own FLAIM session and its
		own handle to the database.
*****************************************************************************/
RCODE F_Database::startCPThread( void)
{
	RCODE						rc = NE_XFLM_OK;
	CP_INFO *				pCPInfo = NULL;
	char						szThreadName[ F_PATH_MAX_SIZE];
	char						szBaseName[ 32];
	F_SuperFileClient *	pSFileClient = NULL;

	// Allocate a CP_INFO structure that will be passed into the
	// thread when it is created.

	if (RC_BAD( rc = f_calloc( (FLMUINT)(sizeof( CP_INFO)), &pCPInfo)))
	{
		goto Exit;
	}
	pCPInfo->pDatabase = this;
	
	// Create a "wait" semaphore
	
	if( RC_BAD( rc = f_semCreate( &pCPInfo->hWaitSem)))
	{
		goto Exit;
	}

	// Allocate a super file handle.

	if( (pCPInfo->pSFileHdl = f_new F_SuperFileHdl) == NULL)
	{
		rc = RC_SET( NE_XFLM_MEM);
		goto Exit;
	}
	
	if( (pSFileClient = f_new F_SuperFileClient) == NULL)
	{
		rc = RC_SET( NE_XFLM_MEM);
		goto Exit;
	}
	
	if( RC_BAD( rc = pSFileClient->setup( m_pszDbPath, m_pszDataDir,
		m_uiMaxFileSize)))
	{
		goto Exit;
	}

	// Set up the super file

	if( RC_BAD( rc = pCPInfo->pSFileHdl->setup( pSFileClient, 
		gv_XFlmSysData.pFileHdlCache, gv_XFlmSysData.uiFileOpenFlags,
		gv_XFlmSysData.uiFileCreateFlags)))
	{
		goto Exit;
	}

	f_memset( &pCPInfo->Stats, 0, sizeof( XFLM_STATS));
	pCPInfo->bStatsInitialized = TRUE;

	// Generate the thread name

	if (RC_BAD( rc = gv_XFlmSysData.pFileSystem->pathReduce( m_pszDbPath, 
		szThreadName, szBaseName)))
	{
		goto Exit;
	}

	f_sprintf( (char *)szThreadName, "Checkpoint (%s)", (char *)szBaseName);

	// Start the checkpoint thread.

	if (RC_BAD( rc = gv_XFlmSysData.pThreadMgr->createThread( &m_pCPThrd,
		flmCPThread, szThreadName, gv_XFlmSysData.uiCheckpointThreadGroup,
		0, pCPInfo, NULL, 32000)))
	{
		goto Exit;
	}

	m_pCPInfo = pCPInfo;
	pCPInfo = NULL;

Exit:

	if( pCPInfo)
	{
		flmFreeCPInfo( &pCPInfo);
	}
	
	if( pSFileClient)
	{
		pSFileClient->Release();
	}
	
	return( rc);
}
Пример #21
0
/***************************************************************************
Desc:	Constructor for F_Db object.
****************************************************************************/
F_Db::F_Db(
	FLMBOOL	bInternalOpen)
{
	m_pDatabase = NULL;
	m_pDict = NULL;
	m_pNextForDatabase = NULL;
	m_pPrevForDatabase = NULL;
	m_pvAppData = NULL;
	m_uiThreadId = 0;
	m_bMustClose = FALSE;
	m_pSFileHdl = NULL;
	m_uiFlags = bInternalOpen ? FDB_INTERNAL_OPEN : 0;
	m_uiTransCount = 0;
	m_eTransType = XFLM_NO_TRANS;
	m_AbortRc = NE_XFLM_OK;
	m_ui64CurrTransID = 0;
	m_uiFirstAvailBlkAddr = 0;
	m_uiLogicalEOF = 0;
	m_uiUpgradeCPFileNum = 0;
	m_uiUpgradeCPOffset = 0;
	m_uiTransEOF = 0;
	f_memset( &m_TransStartTime, 0, sizeof( m_TransStartTime));
	m_bHadUpdOper = FALSE;
	m_uiBlkChangeCnt = 0;
	m_pIxdFixups = NULL;
	m_pNextReadTrans = NULL;
	m_pPrevReadTrans = NULL;
	m_uiInactiveTime = 0;
	m_uiKilledTime = 0;
	m_bItemStateUpdOk = FALSE;
	m_pDeleteStatus = NULL;
	m_pIxClient = NULL;
	m_pIxStatus = NULL;
	m_pCommitClient = NULL;
	m_pStats = NULL;
	m_pDbStats = NULL;
	m_pLFileStats = NULL;
	m_uiLFileAllocSeq = 0;
	f_memset( &m_Stats, 0, sizeof( m_Stats));
	m_bStatsInitialized = TRUE;
	m_pIxStartList = NULL;
	m_pIxStopList = NULL;
	m_pCachedBTree = NULL;
	m_pKeyColl = NULL;
	m_pOldNodeList = NULL;
	m_uiDirtyNodeCount = 0;
	m_hWaitSem = F_SEM_NULL;
	
	m_bKrefSetup = FALSE;
	m_pKrefTbl = NULL;
	m_uiKrefTblSize = 0;
	m_uiKrefCount = 0;
	m_uiTotalKrefBytes = 0;
	m_pucKrefKeyBuf = NULL;
	m_pKrefPool = NULL;
	m_bReuseKrefPool = FALSE;
	m_bKrefCompoundKey = FALSE;
	m_pKrefReset = NULL;
	
	m_tmpKrefPool.poolInit( DEFAULT_KREF_POOL_BLOCK_SIZE);
	m_tempPool.poolInit( XFLM_MAX_KEY_SIZE * 4);
}
Пример #22
0
/****************************************************************************
 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);


}
Пример #23
0
/****************************************************************************
Name:	insert
Desc:
*****************************************************************************/
RCODE F_DynamicList::insert(
	FLMUINT					uiKey,
	F_DLIST_DISP_HOOK 	pDisplayHook,
	void *					pvData,
	FLMUINT					uiDataLen)
{
	RCODE				rc = NE_FLM_OK;
	DLIST_NODE *	pTmp;
	DLIST_NODE *	pNew = NULL;

	if( getNode( uiKey) != NULL)
	{
		rc = RC_SET( NE_FLM_EXISTS);
		goto Exit;
	}

	// Allocate the new node

	if( RC_BAD( rc = f_alloc( sizeof( DLIST_NODE), &pNew)))
	{
		goto Exit;
	}

	f_memset( pNew, 0, sizeof( DLIST_NODE));

	// Set the members of the new node

	pNew->uiKey = uiKey;

	if( pDisplayHook)
	{
		pNew->pDispHook = pDisplayHook;
	}
	else
	{
		pNew->pDispHook = dlistDefaultDisplayHook;
	}

	if( uiDataLen)
	{
		if( RC_BAD( rc = f_alloc( uiDataLen, &pNew->pvData)))
		{
			goto Exit;
		}

		f_memcpy( pNew->pvData, pvData, uiDataLen);
		pNew->uiDataLen = uiDataLen;
	}

	// Find the insertion point

	if( !m_pFirst)
	{
		m_pFirst = m_pLast = m_pCur = pNew;
	}
	else
	{
		pTmp = m_pFirst;
		while( pTmp && pTmp->uiKey < uiKey)
		{
			pTmp = pTmp->pNext;
		}

		if( pTmp)
		{
			if( pTmp == m_pFirst)
			{
				pNew->pNext = m_pFirst;
				m_pFirst->pPrev = pNew;
				m_pFirst = pNew;
			}
			else
			{
				pNew->pNext = pTmp;
				pNew->pPrev = pTmp->pPrev;

				if( pTmp->pPrev)
				{
					pTmp->pPrev->pNext = pNew;
				}

				pTmp->pPrev = pNew;
			}
		}
		else
		{
			// Insert at end
			m_pLast->pNext = pNew;
			pNew->pPrev = m_pLast;
			m_pLast = pNew;
		}
	}

	m_bChanged = TRUE;

Exit:

	if( RC_BAD( rc))
	{
		if( pNew)
		{
			freeNode( pNew);
		}
	}

	return( rc);
}
Пример #24
0
/****************************************************************************
Desc : Checks for physical corruption in a FLAIM database.
DNote: The routine verifies the database by first reading through
		 the database to count certain block types which are in linked lists.
		 It then verifies the linked lists.  It also verifies the B-TREEs
		 in the database.  The reason for the first pass is so that when we
		 verify the linked lists, we can keep ourselves from getting into
		 an infinite loop if there is a loop in the lists.
****************************************************************************/
RCODE F_DbCheck::dbCheck(
	const char *		pszDbFileName,
		// [IN] Full path and file name of the database which
		// is to be checked.  NULL can be passed as the value of
		// this parameter if pDb is non-NULL.
	const char *		pszDataDir,
		// [IN] Directory for data files.
	const char *		pszRflDir,
		// [IN] RFL directory.  NULL can be passed as the value of
		// this parameter to indicate that the log files are located
		// in the same directory as the database or if pDb is non-NULL.
	const char *		pszPassword,
		// [IN] Database password. Needed to open the database if the database
		// key has been wrapped in a password. NULL by default.
	FLMUINT				uiFlags,
		// [IN] Check flags.  Possible flags include:
		//
		//		XFLM_ONLINE. This flag instructs the check to repair any
		//		index corruptions it finds.  The database must have been
		//		opened in read/write mode in order for the check to
		//		successfully repair corruptions.  An update transaction
		//		will be started whenever a corruption is repaired.
		//
		//		XFLM_DO_LOGICAL_CHECK.  This flag instructs the check to
		//		perform a logical check of the databases's indexes
		//		in addition to the structural check.
		//
		//		XFLM_SKIP_DOM_LINK_CHECK.  This flag instructs the check to skip
		//		verifying the DOM links.  This check can take quite a long time
		//		to execute.
		//
		//		XFLM_ALLOW_LIMITED_MODE. This flag instructs the check to allow
		//		the database to be opened in limited mode if the database key is
		//		wrapped in a password and the password we pass is	incorrect 
		//		(or non-existent).
	IF_DbInfo **			ppDbInfo,
		// [IN] Pointer to a DB_INFO structure which is used to store
		// statistics collected during the database check.
	IF_DbCheckStatus *	pDbCheckStatus
		// [IN] Status interface.  Functions in this interface are called 
		// periodically to iform the calling application of the progress
		// being made.  This allows the application to monitor and/or display
		// the progress of the database check.  NULL may be passed as the
		// value of this parameter if the callback feature is not needed.
	)
{
	RCODE								rc = NE_XFLM_OK;
	FLMBYTE *						pBlk = NULL;
	FLMUINT							uiFileEnd;
	FLMUINT							uiBlockSize;
	FLMUINT							uiLoop;
	FLMUINT64						ui64TmpSize;
	FLMBOOL							bStartOver;
	FLMBOOL							bOkToCloseTrans = FALSE;
	FLMBOOL							bAllowLimitedMode =  ( uiFlags & XFLM_ALLOW_LIMITED_MODE)
																		? TRUE
																		: FALSE;

	if (RC_BAD( rc = gv_pXFlmDbSystem->dbOpen( pszDbFileName, pszDataDir,
		pszRflDir, pszPassword, bAllowLimitedMode, (IF_Db **)&m_pDb)))
	{
		goto Exit;
	}

	if ((m_pDbInfo = f_new F_DbInfo) == NULL)
	{
		rc = RC_SET( NE_XFLM_MEM);
		goto Exit;
	}
	if (ppDbInfo)
	{
		*ppDbInfo = m_pDbInfo;
		(*ppDbInfo)->AddRef();
	}

	m_pDbCheckStatus = pDbCheckStatus;
	m_LastStatusRc = NE_XFLM_OK;

	// Get the file size...

	if (uiFlags & XFLM_SKIP_DOM_LINK_CHECK)
	{
		m_bSkipDOMLinkCheck = TRUE;
	}

	// Initialize the information block and Progress structure.

	// Since we know that the check will start read transactions
	// during its processing, set the flag to indicate that the KRef table
	// should be cleaned up on exit if we are still in a read transaction.

	bOkToCloseTrans = TRUE;
	uiBlockSize = m_pDb->m_pDatabase->getBlockSize();

	// Allocate memory to use for reading through the data blocks.

	if( RC_BAD( rc = f_alloc( uiBlockSize, &pBlk)))
	{
		goto Exit;
	}

	if ((m_pBtPool = f_new F_BtPool) == NULL)
	{
		rc = RC_SET( NE_XFLM_MEM);
		goto Exit;
	}

	if (RC_BAD( rc = m_pBtPool->btpInit()))
	{
		goto Exit;
	}
	
	// Setup the result set database.
	
	if( RC_BAD( rc = FlmAllocRandomGenerator( &m_pRandGen)))
	{
		goto Exit;
	}

	m_pRandGen->setSeed( 9768);

	if (RC_BAD( rc = createAndOpenResultSetDb()))
	{
		goto Exit;
	}

Begin_Check:

	// Initialize all statistics in the DB_INFO structure.

	rc = NE_XFLM_OK;
	bStartOver = FALSE;

	m_pDbInfo->m_ui64FileSize = 0;
	m_pDbInfo->freeLogicalFiles();
	m_bPhysicalCorrupt = FALSE;
	m_bIndexCorrupt = FALSE;
	m_uiFlags = uiFlags;
	m_bStartedUpdateTrans = FALSE;
	f_memset( &m_pDbInfo->m_AvailBlocks, 0, sizeof( BLOCK_INFO));
	f_memset( &m_pDbInfo->m_LFHBlocks, 0, sizeof( BLOCK_INFO));

	f_memset( &m_Progress, 0, sizeof( XFLM_PROGRESS_CHECK_INFO));

	/* Get the dictionary information for the file. */

	if (RC_BAD( rc = getDictInfo()))
	{
		goto Exit;
	}

	m_Progress.ui64BytesExamined = 0;

	for (uiLoop = 1;
		  uiLoop <= MAX_DATA_BLOCK_FILE_NUMBER;
		  uiLoop++)
	{
		if (RC_BAD( m_pDb->m_pSFileHdl->getFileSize( uiLoop, &ui64TmpSize)))
		{
			break;
		}
		
		m_Progress.ui64FileSize += ui64TmpSize;
	}

	// See if we have a valid end of file

	uiFileEnd = m_pDb->m_uiLogicalEOF;
	if (FSGetFileOffset( uiFileEnd) % uiBlockSize != 0)
	{
		if (RC_BAD( rc = chkReportError( FLM_BAD_FILE_SIZE, XFLM_LOCALE_NONE,
			0, 0, 0xFF, (FLMUINT32)uiFileEnd, 0, 0, 0)))
		{
			goto Exit;
		}
	}
	else if (m_Progress.ui64FileSize <
					FSGetSizeInBytes( m_pDb->m_pDatabase-> getMaxFileSize(),
																		uiFileEnd))
	{
		m_Progress.ui64FileSize =
					FSGetSizeInBytes( m_pDb->m_pDatabase->getMaxFileSize(),
																uiFileEnd);
	}

	m_pDbInfo->m_ui64FileSize = m_Progress.ui64FileSize;

	// Verify the LFH blocks, B-Trees, and the AVAIL list.

	if( RC_BAD( rc = verifyLFHBlocks( &bStartOver)))
	{
		goto Exit;
	}
	if (bStartOver)
	{
		goto Begin_Check;
	}

	// Check the b-trees.
	
	if (RC_BAD( rc = verifyBTrees( &bStartOver)))
	{
		goto Exit;
	}
	if (bStartOver)
	{
		goto Begin_Check;
	}

	// Check the avail list.

	if (RC_BAD( rc = verifyAvailList( &bStartOver)))
	{
		goto Exit;
	}
	if (bStartOver)
	{
		goto Begin_Check;
	}

Exit:

	if ((m_bPhysicalCorrupt || m_bIndexCorrupt) &&
		 !gv_pXFlmDbSystem->errorIsFileCorrupt( rc))
	{
		rc = RC_SET( NE_XFLM_DATA_ERROR);
	}

	if (RC_OK( rc) && RC_BAD( m_LastStatusRc))
	{
		rc = m_LastStatusRc;
	}

	if (m_pDb)
	{
		// Close down the transaction, if one is going

		if( bOkToCloseTrans &&
			m_pDb->getTransType( ) == XFLM_READ_TRANS)
		{
			m_pDb->krefCntrlFree();
			m_pDb->transAbort();
		}
	}
	
	// Free memory, if allocated

	if (pBlk)
	{
		f_free( &pBlk);
	}

	// Close the FLAIM database we opened.

	if (m_pDb)
	{
		m_pDb->Release();
		m_pDb = NULL;
	}

	return( rc);
}
Пример #25
0
/****************************************************************************
Desc : Adds a value to the selection criteria of a given cursor.
****************************************************************************/
FLMEXP RCODE FLMAPI FlmCursorAddValue(
	HFCURSOR		hCursor,
	QTYPES		eValType,
	void *		pVal,
	FLMUINT		uiValLen
	)
{
	RCODE			rc = FERR_OK;
	FLMUINT		uiVal;
	void *		pTmpVal = pVal;
	CURSOR *		pCursor = (CURSOR *)hCursor;
	F_Pool		pool;
	FLMBOOL		bPoolInitialized = FALSE;

	if (!pCursor)
	{
		flmAssert( 0);
		rc = RC_SET( FERR_INVALID_PARM);
		goto Exit;
	}
	
	if (RC_BAD( rc = pCursor->rc))
	{
		goto Exit;
	}

	// If a read operation has already been performed on this query, no
	// selection criteria may be added.
	
	if (pCursor->bOptimized)
	{
		rc = RC_SET( FERR_ILLEGAL_OP);
		goto Exit;
	}
	
	if (!( pCursor->QTInfo.uiExpecting & FLM_Q_OPERAND))
	{
		rc = RC_SET( FERR_CURSOR_SYNTAX);
		goto Exit;
	}

	switch (eValType)
	{

		// Convert all string types to FLM_TEXT_VALUE 
		//	in order to handle pure unicode coming in.

		case FLM_UNICODE_VAL:
		case FLM_STRING_VAL:
		{
			NODE	node;

			f_memset( &node, 0, sizeof(NODE));

			pool.poolInit( 512);
			bPoolInitialized = TRUE;

			rc = (eValType == FLM_UNICODE_VAL) 
					? GedPutUNICODE( &pool, &node, (FLMUNICODE *) pVal)
					: GedPutNATIVE( &pool, &node, (const char *)pVal);
			if (RC_BAD( rc))
			{
				goto Exit;
			}

			pTmpVal = GedValPtr( &node);
			uiValLen = GedValLen( &node);
			eValType = FLM_TEXT_VAL;
			break;
		}

		case FLM_BOOL_VAL:
			if (!pVal)
			{
				uiVal = FLM_UNK;
			}
			else
			{
				FLMBOOL bTrueFalse = (FLMBOOL)*(FLMBOOL *)pVal;
				uiVal = (bTrueFalse) ? FLM_TRUE : FLM_FALSE;
			}
			pTmpVal = &uiVal;
			eValType = FLM_BOOL_VAL;
			break;

		case FLM_INT32_VAL:
		case FLM_UINT32_VAL:
		case FLM_REC_PTR_VAL:
		case FLM_UINT64_VAL:
		case FLM_INT64_VAL:
		case FLM_TEXT_VAL:
		case FLM_BINARY_VAL:
		
			// pTmpVal is already pointing to pVal, and
			// eValType does not need to be changed.
			
			break;

		default:
			flmAssert( 0);
			rc = RC_SET( FERR_CURSOR_SYNTAX);
			break;
	}

	if (RC_OK( rc = flmCurMakeQNode( &pCursor->QueryPool, eValType, pTmpVal,
									uiValLen, pCursor->QTInfo.uiFlags,
									&(pCursor->QTInfo.pCurAtomNode))))
	{
		if (pCursor->QTInfo.pCurOpNode)
		{
			flmCurLinkLastChild( pCursor->QTInfo.pCurOpNode,
					pCursor->QTInfo.pCurAtomNode);
		}
		pCursor->QTInfo.uiExpecting &= ~FLM_Q_OPERAND;
		pCursor->QTInfo.uiExpecting |= FLM_Q_OPERATOR;
	}

Exit:

	if (pCursor)
	{
		pCursor->rc = rc;
	}

	if (bPoolInitialized)
	{
		pool.poolFree();
	}
	
	return( rc);
}
Пример #26
0
/****************************************************************************
Desc:	Closes all data files associated with the object
****************************************************************************/
void F_MultiFileHdl::closeFile(
	FLMBOOL			bDelete)
{
	RCODE					rc = NE_FLM_OK;
	FLMUINT				uiLoop;
	IF_DirHdl *			pDir = NULL;
	char					szTmpPath[ F_PATH_MAX_SIZE];
	IF_FileSystem *	pFileSystem = f_getFileSysPtr();

	if( !m_bOpen)
	{
		return;
	}

	for( uiLoop = 0; uiLoop < F_MULTI_FHDL_LIST_SIZE; uiLoop++)
	{
		if( m_pFileHdlList[ uiLoop].pFileHdl)
		{
			if( m_pFileHdlList[ uiLoop].bDirty)
			{
				(void)m_pFileHdlList[ uiLoop].pFileHdl->flush();
			}
			m_pFileHdlList[ uiLoop].pFileHdl->closeFile();
			m_pFileHdlList[ uiLoop].pFileHdl->Release();
			f_memset( &m_pFileHdlList[ uiLoop], 0, sizeof( FH_INFO));
		}
	}

	m_ui64EOF = 0;
	m_bOpen = FALSE;

	if( bDelete)
	{
		if( RC_OK( pFileSystem->openDir(
			m_szPath, "*.64", &pDir)))
		{
			// Remove all data files

			for( rc = pDir->next(); !RC_BAD( rc) ; rc = pDir->next())
			{
				pDir->currentItemPath( szTmpPath);
				f_assert( f_strstr( szTmpPath, ".64") != 0);
				(void)pFileSystem->deleteFile( szTmpPath);
			}

			pDir->Release();
			pDir = NULL;
		}

		// Release and delete the lock file

		(void)releaseLockFile( m_szPath, TRUE);

		// Remove the directory

		(void)pFileSystem->removeDir( m_szPath);
	}
	else
	{
		(void)releaseLockFile( m_szPath, FALSE);
	}
}
Пример #27
0
/****************************************************************************
Desc : Return the status of the index.
****************************************************************************/
FLMEXP RCODE FLMAPI FlmIndexStatus(
	HFDB					hDb,
	FLMUINT				uiIndexNum,
	FINDEX_STATUS *	pIndexStatus)
{
	RCODE					rc = FERR_OK;
	FLMBOOL				bStartedAutoTrans = FALSE;
	FLMUINT 				uiLastDrnIndexed;
	FDB *					pDb = (FDB *)hDb;
	F_BKGND_IX *		pBackgroundIx;
	FLMBOOL				bSuspended;
	FLMBOOL				bMutexLocked = FALSE;

	flmAssert( pIndexStatus != NULL);

	if( IsInCSMode( hDb))
	{
		fdbInitCS( pDb);
		rc = flmIndexStatusCS( pDb, uiIndexNum, pIndexStatus);
		goto Exit;
	}

	if( RC_BAD( rc = fdbInit( (FDB *)hDb, FLM_READ_TRANS,
							FDB_TRANS_GOING_OK, 0, &bStartedAutoTrans)))
	{
		goto Exit;
	}

	f_mutexLock( gv_FlmSysData.hShareMutex);
	bMutexLocked = TRUE;

	pBackgroundIx = flmBackgroundIndexGet( pDb->pFile, uiIndexNum, TRUE);
	if( pBackgroundIx)
	{
		f_memcpy( pIndexStatus, &pBackgroundIx->indexStatus, 
			sizeof( FINDEX_STATUS));
		f_mutexUnlock( gv_FlmSysData.hShareMutex);
		bMutexLocked = FALSE;
		flmAssert( pIndexStatus->uiIndexNum == uiIndexNum);
	}
	else
	{
		IXD *		pIxd;
		FLMBOOL	bTrackerIxSuspended;

		if( RC_BAD( rc = fdictGetIndex( 
			pDb->pDict, pDb->pFile->bInLimitedMode,
			uiIndexNum,NULL, &pIxd, TRUE)))
		{
			goto Exit;
		}

		bSuspended = (pIxd->uiFlags & IXD_SUSPENDED)
												? TRUE
												: FALSE;

		f_mutexUnlock( gv_FlmSysData.hShareMutex);
		bMutexLocked = FALSE;

		// Get the index state from the tracker

		if( RC_BAD( rc = flmGetIxTrackerInfo( pDb, uiIndexNum, 
			NULL, &uiLastDrnIndexed, NULL, &bTrackerIxSuspended)))
		{
			if( rc == FERR_NOT_FOUND)
			{
				rc = RC_SET( FERR_BAD_IX);
			}
			goto Exit;
		}

		// Sanity check

#ifdef FLM_DEBUG
		if( pDb->pFile->FileHdr.uiVersionNum >= FLM_FILE_FORMAT_VER_4_51 &&
			bSuspended != bTrackerIxSuspended)
		{
			flmAssert( 0);
		}
#endif

		// Populate the index status structure.

		f_memset( pIndexStatus, 0, sizeof( FINDEX_STATUS));
		pIndexStatus->uiIndexNum = uiIndexNum;
		pIndexStatus->uiLastRecordIdIndexed = uiLastDrnIndexed;
		pIndexStatus->bSuspended = bSuspended;
	}

Exit:

	if( bMutexLocked)
	{
		f_mutexUnlock( gv_FlmSysData.hShareMutex);
	}

	if( bStartedAutoTrans)
	{
		rc = flmEndAutoTrans( pDb, rc);
	}
	flmExit( FLM_INDEX_STATUS, pDb, rc);
	return( rc);
}
Пример #28
0
/****************************************************************************
Desc: Reads data from the file
****************************************************************************/
RCODE F_MultiFileHdl::read(
	FLMUINT64	ui64Offset,				// Offset to begin reading
	FLMUINT		uiLength,				// Number of bytes to read
	void *		pvBuffer,				// Buffer
	FLMUINT *	puiBytesRead)			// [out] Number of bytes read
{
	RCODE				rc = NE_FLM_OK;
	FLMUINT			uiFileNum = getFileNum( ui64Offset);
	FLMUINT			uiFileOffset = getFileOffset( ui64Offset);
	FLMUINT			uiTmp;
	FLMUINT			uiTotalBytesRead = 0;
	FLMUINT			uiBytesToRead;
	FLMUINT			uiMaxReadLen;
	IF_FileHdl *	pFileHdl;

	// Handle the case of a 0-byte read

	if( !uiLength)
	{
		if( ui64Offset >= m_ui64EOF)
		{
			rc = RC_SET( NE_FLM_IO_END_OF_FILE);
		}
		goto Exit;
	}

	// Read the data file(s), moving to new files as needed.

	for( ;;)
	{
		if( ui64Offset >= m_ui64EOF)
		{
			rc = RC_SET( NE_FLM_IO_END_OF_FILE);
			goto Exit;
		}

		uiMaxReadLen = m_uiMaxFileSize - uiFileOffset;
		f_assert( uiMaxReadLen != 0);
		uiTmp = (uiLength >= uiMaxReadLen ? uiMaxReadLen : uiLength);
		uiBytesToRead = (((FLMUINT64)uiTmp > (FLMUINT64)(m_ui64EOF - ui64Offset))
								? (FLMUINT)(m_ui64EOF - ui64Offset)
								: uiTmp);

		if( RC_BAD( rc = getFileHdl( uiFileNum, FALSE, &pFileHdl)))
		{
			if( rc == NE_FLM_IO_PATH_NOT_FOUND)
			{
				// Handle the case of a sparse file by filling the unread
				// portion of the buffer with zeros.

				f_memset( pvBuffer, 0, uiBytesToRead);
				uiTmp = uiBytesToRead;
				rc = NE_FLM_OK;
			}
			else
			{
				goto Exit;
			}
		}
		else
		{
			if( RC_BAD( rc = pFileHdl->read( uiFileOffset, uiBytesToRead,
				pvBuffer, &uiTmp)))
			{
				if( rc == NE_FLM_IO_END_OF_FILE)
				{
					// Handle the case of a sparse file by filling the unread
					// portion of the buffer with zeros.

					f_memset( &(((FLMBYTE *)(pvBuffer))[ uiTmp]),
						0, (FLMUINT)(uiBytesToRead - uiTmp));
					uiTmp = uiBytesToRead;
					rc = NE_FLM_OK;
				}
				else
				{
					goto Exit;
				}
			}
		}

		uiTotalBytesRead += uiTmp;
		uiLength -= uiTmp;
		if( !uiLength)
		{
			break;
		}

		// Set up for next read

		pvBuffer = ((FLMBYTE *)pvBuffer) + uiTmp;
		ui64Offset += uiTmp;
		uiFileNum = getFileNum( ui64Offset);
		uiFileOffset = getFileOffset( ui64Offset);
	}

Exit:

	*puiBytesRead = uiTotalBytesRead;
	return( rc);
}
Пример #29
0
/****************************************************************************
Desc: This routine links a request into a notification list and
		then waits to be notified that the event has occurred.  The mutex
		is assumed to protect the notify list.
****************************************************************************/
RCODE FLMAPI f_notifyWait(
	F_MUTEX						hMutex,
	F_SEM							hSem,
	void *						pvData,
	F_NOTIFY_LIST_ITEM **	ppNotifyList)
{
	RCODE							rc = NE_FLM_OK;
	RCODE							tmpRc;
	F_NOTIFY_LIST_ITEM		stackNotify;
	F_NOTIFY_LIST_ITEM *		pNotify = &stackNotify;
	
	f_assertMutexLocked( hMutex);
	f_assert( pNotify != *ppNotifyList);

	f_memset( &stackNotify, 0, sizeof( F_NOTIFY_LIST_ITEM));
	
	pNotify->uiThreadId = f_threadId();
	pNotify->hSem = F_SEM_NULL;
	
	if( hSem == F_SEM_NULL)
	{
		if( RC_BAD( rc = f_semCreate( &pNotify->hSem)))
		{
			goto Exit;
		}
	}
	else
	{
		pNotify->hSem = hSem;
	}
	
	pNotify->pRc = &rc;
	pNotify->pvData = pvData;
	
	pNotify->pNext = *ppNotifyList;
	*ppNotifyList = pNotify;

	// Unlock the mutex and wait on the semaphore

	f_mutexUnlock( hMutex);

	if( RC_BAD( tmpRc = f_semWait( pNotify->hSem, F_WAITFOREVER)))
	{
		rc = tmpRc;
	}

	// Free the semaphore
	
	if( hSem != pNotify->hSem)
	{
		f_semDestroy( &pNotify->hSem);
	}

	// Relock the mutex

	f_mutexLock( hMutex);

Exit:

	return( rc);
}
Пример #30
0
/****************************************************************************
Desc:	Build a text key.
****************************************************************************/
FSTATIC RCODE flmAddTextKeyPiece(
	SQL_PRED *		pPred,
	F_INDEX *		pIndex,
	FLMUINT			uiKeyComponent,
	ICD *				pIcd,
	F_DataVector *	pFromSearchKey,
	FLMBYTE *		pucFromKey,
	FLMUINT *		puiFromKeyLen,
	F_DataVector *	pUntilSearchKey,
	FLMBYTE *		pucUntilKey,
	FLMUINT *		puiUntilKeyLen,
	FLMBOOL *		pbCanCompareOnKey,
	FLMBOOL *		pbFromIncl,
	FLMBOOL *		pbUntilIncl)
{
	RCODE       			rc = NE_SFLM_OK;
	FLMBYTE *				pucFromKeyLenPos;
	FLMBYTE *				pucUntilKeyLenPos;
	FLMUINT					uiLanguage = pIndex->uiLanguage;
	FLMUINT					uiFromCollationLen = 0;
	FLMUINT					uiUntilCollationLen = 0;
	FLMUINT					uiCharCount;
	FLMUINT					uiFromCaseLen;
	FLMUINT					uiUntilCaseLen;
	FLMBOOL					bFromOriginalCharsLost = FALSE;
	FLMBOOL					bUntilOriginalCharsLost = FALSE;
	FLMBOOL					bIsDBCS = (uiLanguage >= FLM_FIRST_DBCS_LANG &&
								  uiLanguage <= FLM_LAST_DBCS_LANG)
								  ? TRUE
								  : FALSE;

	FLMBOOL					bCaseInsensitive = (FLMBOOL)((pPred->uiCompareRules &
															FLM_COMP_CASE_INSENSITIVE)
															? TRUE
															: FALSE);
	FLMBOOL					bDoFirstSubstring = (FLMBOOL)((pIcd->uiFlags & ICD_SUBSTRING)
															 ? TRUE
															 : FALSE);
	FLMBOOL					bDoMatchBegin = FALSE;
	FLMBOOL					bTrailingWildcard = FALSE;
	const FLMBYTE *		pucFromUTF8Buf = NULL;
	FLMUINT					uiFromBufLen = 0;
	const FLMBYTE *		pucUntilUTF8Buf = NULL;
	FLMUINT					uiUntilBufLen = 0;
	FLMUINT					uiWildcardPos;
	FLMBOOL					bFromDataTruncated;
	FLMBOOL					bUntilDataTruncated;
	FLMUINT					uiFromFlags = 0;
	FLMUINT					uiUntilFlags = 0;
	FLMUINT					uiCompareRules;
	FLMBOOL					bAscending = (pIcd->uiFlags & ICD_DESCENDING) ? FALSE: TRUE;
	F_BufferIStream		bufferIStream;
	FLMUINT					uiFromKeyLen = *puiFromKeyLen;
	FLMUINT					uiUntilKeyLen = *puiUntilKeyLen;
	FLMUINT					uiFromComponentLen;
	FLMUINT					uiUntilComponentLen;
	FLMUINT					uiFromSpaceLeft;
	FLMUINT					uiUntilSpaceLeft;
	
	// Leave room for the component length

	pucFromKeyLenPos = pucFromKey + uiFromKeyLen;
	pucUntilKeyLenPos = pucUntilKey + uiUntilKeyLen;
	pucFromKey = pucFromKeyLenPos + 2;
	pucUntilKey = pucUntilKeyLenPos + 2;
	uiFromSpaceLeft = SFLM_MAX_KEY_SIZE - uiFromKeyLen - 2;
	uiUntilSpaceLeft = SFLM_MAX_KEY_SIZE - uiUntilKeyLen - 2;

	switch (pPred->eOperator)
	{

		// The difference between MATCH and EQ_OP is that EQ does
		// not support wildcards embedded in the search key.

		case SQL_MATCH_OP:
			flmAssert( pPred->pFromValue->eValType == SQL_UTF8_VAL);
			pucFromUTF8Buf = pPred->pFromValue->val.str.pszStr;
			uiFromBufLen = pPred->pFromValue->val.str.uiByteLen;
			uiCompareRules = pIcd->uiCompareRules;

			if (RC_BAD( rc = flmUTF8FindWildcard( pucFromUTF8Buf, &uiWildcardPos,
										&uiCompareRules)))
			{
				goto Exit;
			}
			
			// If there is no wildcard, uiWildcardPos will be FLM_MAX_UINT
			
			if (uiWildcardPos != FLM_MAX_UINT)
			{

				// If wildcard is in position 0, it is NOT
				// a match begin.

				if (uiWildcardPos)
				{
					bDoMatchBegin = TRUE;
					uiFromBufLen = uiWildcardPos;
				}
			}
			if (!(pIcd->uiFlags & ICD_SUBSTRING))
			{

				// Index is NOT a substring index

				if (!bDoMatchBegin)
				{

					// Wildcard was at the beginning, will have
					// to search the index from first to last

					pucFromUTF8Buf = NULL;
				}
				else
				{
					bTrailingWildcard = TRUE;
				}
			}
			else
			{
				FLMBOOL	bNotUsingFirstOfString;

				// If this is a substring index look for a 
				// better 'contains' string to search for. 
				// We don't like "A*BCDEFG" searches.
				
				bTrailingWildcard = bDoMatchBegin;

				uiCompareRules = pIcd->uiCompareRules;
				if (RC_BAD( rc = flmSelectBestSubstr( &pucFromUTF8Buf,
					&uiFromBufLen, 
					&uiCompareRules, &bTrailingWildcard,
					&bNotUsingFirstOfString)))
				{
					goto Exit;
				}

				if (bNotUsingFirstOfString)
				{
					bDoMatchBegin = bTrailingWildcard;
					*pbCanCompareOnKey = FALSE;
					bDoFirstSubstring = FALSE;
				}
				else if (bTrailingWildcard)
				{
					bDoMatchBegin = TRUE;
				}

				if (RC_BAD( rc = flmCountCharacters( pucFromUTF8Buf,
									uiFromBufLen, 2,
									&uiCompareRules, &uiCharCount)))
				{
					goto Exit;
				}
				
				// Special case: Single character contains/MEnd in a substr ix.

				if (!bIsDBCS && uiCharCount < 2)
				{
					pucFromUTF8Buf = NULL;
				}
			}
			
			pucUntilUTF8Buf = pucFromUTF8Buf;
			uiUntilBufLen = uiFromBufLen;
			break;

		case SQL_RANGE_OP:
			if (bAscending)
			{
				if (pPred->pFromValue)
				{
					flmAssert( pPred->pFromValue->eValType == SQL_UTF8_VAL);
					pucFromUTF8Buf = pPred->pFromValue->val.str.pszStr;
					uiFromBufLen = pPred->pFromValue->val.str.uiByteLen;
				}
				else
				{
					// Should have been done up above
					
					// pucFromUTF8Buf = NULL;
					// uiFromBufLen = 0;
				}
				if (pPred->pUntilValue)
				{
					flmAssert( pPred->pUntilValue->eValType == SQL_UTF8_VAL);
					pucUntilUTF8Buf = pPred->pUntilValue->val.str.pszStr;
					uiUntilBufLen = pPred->pUntilValue->val.str.uiByteLen;
				}
				else
				{
					// Should have been done up above.
					
					// pucUntilUTF8Buf = NULL;
					// uiUntilBufLen = 0;
				}
				if (!pPred->bInclFrom)
				{
					uiFromFlags |= EXCLUSIVE_GT_FLAG;
				}
				if (!pPred->bInclUntil)
				{
					uiUntilFlags |= EXCLUSIVE_LT_FLAG;
				}
			}
			else
			{
				if (pPred->pUntilValue)
				{
					flmAssert( pPred->pUntilValue->eValType == SQL_UTF8_VAL);
					pucFromUTF8Buf = pPred->pUntilValue->val.str.pszStr;
					uiFromBufLen = pPred->pUntilValue->val.str.uiByteLen;
				}
				else
				{
					// Should have been done up above
					
					// pucFromUTF8Buf = NULL;
					// uiFromBufLen = 0;
				}
					
				if (pPred->pFromValue)
				{
					flmAssert( pPred->pFromValue->eValType == SQL_UTF8_VAL);
					pucUntilUTF8Buf = pPred->pFromValue->val.str.pszStr;
					uiUntilBufLen = pPred->pFromValue->val.str.uiByteLen;
				}
				else
				{
					// Should have been done up above.
					
					// pucUntilUTF8Buf = NULL;
					// uiUntilBufLen = 0;
				}
				if (!pPred->bInclUntil)
				{
					uiFromFlags |= EXCLUSIVE_GT_FLAG;
				}
				if (!pPred->bInclFrom)
				{
					uiUntilFlags |= EXCLUSIVE_LT_FLAG;
				}
			}
			break;

		case SQL_NE_OP:

			// Set up to do full index scan.
			
			// Buffers should already be NULL.

			// pucFromUTF8Buf = NULL;
			// pucUntilUTF8Buf = NULL;
			break;

		case SQL_APPROX_EQ_OP:

			// Set up to do full index scan.
			
			// Buffers should already be NULL

			// pucFromUTF8Buf = NULL;
			// pucUntilUTF8Buf = NULL;

			// Cannot compare on the key if index is upper case,
			// even if the bCaseInsensitive flag is set.

			if (pIcd->uiCompareRules & FLM_COMP_CASE_INSENSITIVE)
			{
				*pbCanCompareOnKey = FALSE;
			}
			break;

		default:

			// Every predicate should have been converted to one of the above
			// cases, or should be handled by another routine.

			rc = RC_SET_AND_ASSERT( NE_SFLM_QUERY_SYNTAX);
			goto Exit;
	}

	// If index is case insensitive, but search is case sensitive
	// we must NOT do a key match - we would fail things we should
	// not be failing.
	
	if ((pIcd->uiCompareRules & FLM_COMP_CASE_INSENSITIVE) && !bCaseInsensitive)
	{
		*pbCanCompareOnKey = FALSE;
	}
	
	if (!pucFromUTF8Buf)
	{
		uiFromComponentLen = KEY_LOW_VALUE;
	}
	else
	{
		if (RC_BAD( rc = bufferIStream.openStream( 
			(const char *)pucFromUTF8Buf, uiFromBufLen)))
		{
			goto Exit;
		}

		// Add ICD_ESC_CHAR to the icd flags because
		// the search string must have BACKSLASHES and '*' escaped.

		uiFromComponentLen = uiFromSpaceLeft;
		bFromDataTruncated = FALSE;
		if (RC_BAD( rc = KYCollateValue( pucFromKey, &uiFromComponentLen,
								&bufferIStream, SFLM_STRING_TYPE,
							pIcd->uiFlags | ICD_ESC_CHAR, pIcd->uiCompareRules,
							pIcd->uiLimit,
							&uiFromCollationLen, &uiFromCaseLen,
							uiLanguage, bDoFirstSubstring,
							FALSE, &bFromDataTruncated,
							&bFromOriginalCharsLost)))
		{
			goto Exit;
		}
		
		bufferIStream.closeStream();
		
		if (bFromDataTruncated)
		{
			*pbCanCompareOnKey = FALSE;
			
			// Save the original data into pFromSearchKey so the comparison
			// routines can do a comparison on the full value if
			// necessary.

			if (RC_BAD( rc = pFromSearchKey->setUTF8( uiKeyComponent,
										pucFromUTF8Buf, uiFromBufLen)))
			{
				goto Exit;
			}
			uiFromFlags |= (SEARCH_KEY_FLAG | TRUNCATED_FLAG);
		}
		else if (bFromOriginalCharsLost)
		{
			*pbCanCompareOnKey = FALSE;
		}
		
		if (pucFromUTF8Buf != pucUntilUTF8Buf)
		{
			
			// Handle scenario of a case-sensitive index, but search is
			// case-insensitive.

			if (uiFromComponentLen &&
				 (bIsDBCS ||
				   (!(pIcd->uiCompareRules & FLM_COMP_CASE_INSENSITIVE) &&
					 bCaseInsensitive)))
			{
				setFromCaseByte( pucFromKey, &uiFromComponentLen, uiFromCaseLen,
										bIsDBCS, bAscending,
										(uiFromFlags & EXCLUSIVE_GT_FLAG)
										? TRUE
										: FALSE);
			}
		}
	}

	// Do the until key now

	if (!pucUntilUTF8Buf)
	{
		uiUntilComponentLen = KEY_HIGH_VALUE;
	}
	else if (pucFromUTF8Buf == pucUntilUTF8Buf)
	{
		
		// Handle case where from and until buffers are the same.
		// This should only be possible in the equality case or match begin
		// case, in which cases neither the EXCLUSIVE_LT_FLAG or the
		// EXCLUSIVE_GT_FLAG should be set.
		
		flmAssert( uiFromBufLen == uiUntilBufLen);
		flmAssert( !(uiFromFlags & (EXCLUSIVE_GT_FLAG | EXCLUSIVE_LT_FLAG)));
		flmAssert( !(uiUntilFlags & (EXCLUSIVE_GT_FLAG | EXCLUSIVE_LT_FLAG)));
		
		// Need to collate the until key from the original data if
		// the from key was truncated or there is not enough room in
		// the until key.  Otherwise, we can simply copy
		// the from key into the until key - a little optimization.
		
		if (uiUntilSpaceLeft >= uiFromComponentLen && !bFromDataTruncated)
		{
			if ((uiUntilComponentLen = uiFromComponentLen) != 0)
			{
				f_memcpy( pucUntilKey, pucFromKey, uiFromComponentLen);
			}
			uiUntilCaseLen = uiFromCaseLen;
			uiUntilCollationLen = uiFromCollationLen;
			bUntilOriginalCharsLost = bFromOriginalCharsLost;
			bUntilDataTruncated = FALSE;
		}
		else
		{
			if (RC_BAD( rc = bufferIStream.openStream( 
				(const char *)pucUntilUTF8Buf, uiUntilBufLen)))
			{
				goto Exit;
			}
	
			// Add ICD_ESC_CHAR to the icd flags because
			// the search string must have BACKSLASHES and '*' escaped.
	
			uiUntilComponentLen = uiUntilSpaceLeft;
			bUntilDataTruncated = FALSE;
			if (RC_BAD( rc = KYCollateValue( pucUntilKey, &uiUntilComponentLen,
								&bufferIStream, SFLM_STRING_TYPE,
								pIcd->uiFlags | ICD_ESC_CHAR, pIcd->uiCompareRules,
								pIcd->uiLimit,
								&uiUntilCollationLen, &uiUntilCaseLen,
								uiLanguage, bDoFirstSubstring, 
								FALSE, &bUntilDataTruncated,
								&bUntilOriginalCharsLost)))
			{
				goto Exit;
			}
			
			bufferIStream.closeStream();
			
			if (bUntilDataTruncated)
			{
				
				// Save the original data into pUntilSearchKey so the comparison
				// routines can do a comparison on the full value if
				// necessary.
	
				if (RC_BAD( rc = pUntilSearchKey->setUTF8( uiKeyComponent,
											pucUntilUTF8Buf, uiUntilBufLen)))
				{
					goto Exit;
				}
				*pbCanCompareOnKey = FALSE;
				uiUntilFlags |= (SEARCH_KEY_FLAG | TRUNCATED_FLAG);
			}
			else if (bUntilOriginalCharsLost)
			{
				*pbCanCompareOnKey = FALSE;
			}
		}
		
		if (bDoMatchBegin)
		{
			if (bAscending)
			{
				
				// Handle scenario of a case-sensitive index, but search is
				// case-insensitive.
		
				if (uiFromComponentLen &&
					 (bIsDBCS ||
					  (!(pIcd->uiCompareRules & FLM_COMP_CASE_INSENSITIVE) &&
						bCaseInsensitive)))
				{
					setFromCaseByte( pucFromKey, &uiFromComponentLen, uiFromCaseLen,
											bIsDBCS, bAscending, FALSE);
				}
	
				// Fill everything after the collation values in the until
				// key with high values (0xFF)
	
				f_memset( &pucUntilKey[ uiUntilCollationLen], 0xFF,
								uiUntilSpaceLeft - uiUntilCollationLen);
				uiUntilComponentLen = uiUntilSpaceLeft;
			}
			else
			{
				
				if (uiUntilComponentLen &&
					 (bIsDBCS ||
					  (!(pIcd->uiCompareRules & FLM_COMP_CASE_INSENSITIVE) &&
						bCaseInsensitive)))
				{
					// NOTE: Always inclusive because this is a matchbegin.
				
					setUntilCaseByte( pucUntilKey, &uiUntilComponentLen, uiUntilCaseLen,
										bIsDBCS, bAscending, FALSE);
				}
									
				// Fill rest of from key with high values after collation values.
				
				f_memset( &pucFromKey[ uiFromCollationLen], 0xFF,
							uiFromSpaceLeft - uiFromCollationLen);
				uiFromComponentLen = uiFromSpaceLeft;
			}
		}
		else
		{
			if (bDoFirstSubstring)
			{
				FLMUINT	uiBytesToRemove = (bIsDBCS) ? 2 : 1;
				
				if (bAscending)
				{
					
					// Get rid of the first substring byte in the until
					// key.
					
					f_memmove( &pucUntilKey [uiUntilCollationLen],
								  &pucUntilKey [uiUntilCollationLen + uiBytesToRemove],
								  uiUntilComponentLen - uiUntilCollationLen - uiBytesToRemove);
					uiUntilComponentLen -= uiBytesToRemove;
				}
				else
				{
					
					// Descending order - put the string without the
					// first-substring-marker into the from key instead of
					// the until key.
					
					f_memmove( &pucFromKey [uiFromCollationLen],
								  &pucFromKey [uiFromCollationLen + uiBytesToRemove],
								  uiFromComponentLen - uiFromCollationLen - uiBytesToRemove);
					uiFromComponentLen -= uiBytesToRemove;
				}
			
				// Handle scenario of a case-sensitive index, but search is
				// case-insensitive.
		
				if (bIsDBCS ||
					 (!(pIcd->uiCompareRules & FLM_COMP_CASE_INSENSITIVE) &&
					  bCaseInsensitive))
				{
					setFromCaseByte( pucFromKey, &uiFromComponentLen, uiFromCaseLen,
												bIsDBCS, bAscending, FALSE);
					setUntilCaseByte( pucUntilKey, &uiUntilComponentLen, uiUntilCaseLen,
												bIsDBCS, bAscending, FALSE);
				}
			}
		}
	}
	else // pucFromUTF8Buf != pucUntilUTF8Buf
	{
		if (RC_BAD( rc = bufferIStream.openStream( 
			(const char *)pucUntilUTF8Buf, uiUntilBufLen)))
		{
			goto Exit;
		}

		// Add ICD_ESC_CHAR to the icd flags because
		// the search string must have BACKSLASHES and '*' escaped.

		uiUntilComponentLen = uiUntilSpaceLeft;
		bUntilDataTruncated = FALSE;
		if (RC_BAD( rc = KYCollateValue( pucUntilKey, &uiUntilComponentLen,
							&bufferIStream, SFLM_STRING_TYPE,
							pIcd->uiFlags | ICD_ESC_CHAR, pIcd->uiCompareRules,
							pIcd->uiLimit,
							&uiUntilCollationLen, &uiUntilCaseLen,
							uiLanguage, bDoFirstSubstring, 
							FALSE, &bUntilDataTruncated,
							&bUntilOriginalCharsLost)))
		{
			goto Exit;
		}
		
		bufferIStream.closeStream();
		
		if (bUntilDataTruncated)
		{
			
			// Save the original data into pUntilSearchKey so the comparison
			// routines can do a comparison on the full value if
			// necessary.

			if (RC_BAD( rc = pUntilSearchKey->setUTF8( uiKeyComponent,
										pucUntilUTF8Buf, uiUntilBufLen)))
			{
				goto Exit;
			}
			*pbCanCompareOnKey = FALSE;
			uiUntilFlags |= (SEARCH_KEY_FLAG | TRUNCATED_FLAG);
		}
		else if (bUntilOriginalCharsLost)
		{
			*pbCanCompareOnKey = FALSE;
		}

		if (uiUntilComponentLen &&
			 (bIsDBCS ||
			  (!(pIcd->uiCompareRules & FLM_COMP_CASE_INSENSITIVE) &&
			   bCaseInsensitive)))
		{
			setUntilCaseByte( pucUntilKey, &uiUntilComponentLen, uiUntilCaseLen,
									bIsDBCS, bAscending,
									(uiUntilFlags & EXCLUSIVE_LT_FLAG)
									? TRUE
									: FALSE);
		}
	}
	
	UW2FBA( (FLMUINT16)(uiFromKeyLen | uiFromFlags), pucFromKeyLenPos);
	UW2FBA( (FLMUINT16)(uiUntilKeyLen | uiUntilFlags), pucUntilKeyLenPos);
	
	// Set the FROM and UNTIL key length return values.

	uiFromKeyLen += 2;
	if (uiFromComponentLen != KEY_LOW_VALUE)
	{
		uiFromKeyLen += uiFromComponentLen;
		if (!(uiFromFlags & EXCLUSIVE_GT_FLAG))
		{
			*pbFromIncl = TRUE;
		}
	}
	uiUntilKeyLen += 2;
	if (uiUntilComponentLen != KEY_HIGH_VALUE)
	{
		uiUntilKeyLen += uiUntilComponentLen;
		if (!(uiUntilFlags & EXCLUSIVE_LT_FLAG))
		{
			*pbUntilIncl = TRUE;
		}
	}
	
Exit:

	return( rc);
}