/****************************************************************************
Desc:	Read a line from the ini file and store it in pszBuf
****************************************************************************/
RCODE F_IniFile::readLine(
	char *		pszBuf,
	FLMUINT *	puiBytes,
	FLMBOOL *	pbMore)
{
	RCODE			rc = NE_FLM_OK;
	FLMUINT		uiBytesRead = 0;
	FLMUINT		uiBytesInLine = 0;
	FLMUINT		uiEOLBytes = 0;
	FLMBOOL		bEOL = FALSE;
		
	f_assert( m_pFileHdl);
	
	rc = m_pFileHdl->read( m_uiFileOffset, *puiBytes,
		(FLMBYTE *)pszBuf, &uiBytesRead);
	
	if ( RC_OK( rc) || rc == NE_FLM_IO_END_OF_FILE)
	{
		// Check to see if we got more than one line...
		
		while( !bEOL && (uiBytesInLine < uiBytesRead) )
		{
			if( pszBuf[ uiBytesInLine] == 13 || pszBuf[ uiBytesInLine] == 10)
			{
				// NOTE: If we end up reading the first byte of a CR/LF pair, but
				// but the second byte is read on the next call, then it will get
				// counted as a new (but empty) line.  We're not going to worry
				// about it though, because  empty lines end up getting ignored
				// and this isn't likely to happen often enough to effect
				// performance.
				
				bEOL = TRUE;
				*puiBytes = uiBytesInLine;
				uiEOLBytes=1;
				
				// Check for a CR/LF pair (or a LF/CR pair...)
				
				if( (uiBytesInLine + 1 < uiBytesRead) &&
					  (pszBuf[ uiBytesInLine + 1] == 13 ||
						 pszBuf[ uiBytesInLine + 1] == 10))
				{
					uiEOLBytes++;
				}
			}
			else
			{
				uiBytesInLine++;
			}
		}

		// Set the file position variable forward appropriately...
		
		m_uiFileOffset += uiBytesInLine + uiEOLBytes;
	}

	// If we read in more than one line, then don't want to return
	// NE_FLM_IO_END_OF_FILE...
	
	if( rc == NE_FLM_IO_END_OF_FILE && 
		(uiBytesInLine + uiEOLBytes) < uiBytesRead)
	{
		rc = NE_FLM_OK;
	}

	// Last step - update pbMore
	
	*pbMore = (bEOL || (uiBytesRead == 0))
					? FALSE
					: TRUE;
		
	return( rc);
}
Exemple #2
0
/****************************************************************************
Desc:
****************************************************************************/
RCODE createUnitTest(
	const char *		configPath, 
	const char *		buildNum, 
	const char *		environment,  
	const char *		user, 
	unitTestData *		uTD)
{
	RCODE					rc = FERR_OK;
	IF_FileHdl *		pConfigFileHdl = NULL;
	IF_FileHdl *		pCSVFileHdl = NULL;
	FLMBYTE				buffer[ MAX_BUFFER_SIZE] = "";
	FLMUINT				uiSize = MAX_BUFFER_SIZE;
	FLMUINT64			ui64Tmp;
	char *				strPos1 = NULL;
	char *				strPos2 = NULL;
	IF_FileSystem *	pFileSystem = NULL;

	if( !configPath || !buildNum || !environment || !uTD || !user)
	{
		flmAssert(0);
	}

	if( f_strlen(user) > MAX_SMALL_BUFFER_SIZE)
	{
		rc = RC_SET( FERR_CONV_DEST_OVERFLOW);
		goto Exit;
	}
	else
	{
		f_strcpy( uTD->userName, user);
	}

	if( f_strlen(environment) > MAX_SMALL_BUFFER_SIZE)
	{
		rc = RC_SET( FERR_CONV_DEST_OVERFLOW);
		goto Exit;
	}
	else
	{
		f_strcpy( uTD->environment, environment);
	}

	if( f_strlen( buildNum) > MAX_SMALL_BUFFER_SIZE)
	{
		rc = RC_SET( FERR_CONV_DEST_OVERFLOW);
		goto Exit;
	}
	else
	{
		f_strcpy( uTD->buildNumber, buildNum);
	}
	
	if( RC_BAD( rc = FlmGetFileSystem( &pFileSystem)))
	{
		goto Exit;
	}
	
	if( configPath[ 0])
	{
		if( RC_BAD( rc = pFileSystem->openFile(
			configPath, FLM_IO_RDONLY | FLM_IO_SH_DENYNONE, &pConfigFileHdl)))
		{
			goto Exit;
		}
	
		if( RC_BAD( rc = pConfigFileHdl->size( &ui64Tmp)))
		{
			goto Exit;
		}
		
		uiSize = (FLMUINT)ui64Tmp;
		
		if( RC_BAD( rc = pConfigFileHdl->read( 0, uiSize, buffer, &uiSize)))
		{
			goto Exit;
		}
	
		#ifdef FLM_WIN
		{
			char			szTemp[ MAX_BUFFER_SIZE];
			char *		pszTemp = szTemp;
			FLMUINT		uiNewSize = uiSize;
		
			for( unsigned int i = 0; i < uiSize; i++)
			{
				if( ((i + 1) < uiSize) 
					&& (buffer[i] == 0x0D && buffer[ i + 1] == 0x0A))
				{
					*pszTemp++ = 0x0A;
					i++;
					uiNewSize--;
				}
				else
				{
					*pszTemp++ = buffer[ i];
				}
			}
				
			f_memcpy( buffer, szTemp, uiNewSize);
			uiSize = uiNewSize;
		}
		#endif
		
		// Get the FOLDER
		
		strPos1 = f_strchr( (const char *)buffer, ':');
		strPos2 = f_strchr( (const char *)strPos1, '\n');
		
		if( !strPos1 || !strPos2)
		{
			rc = RC_SET( FERR_FAILURE);
			goto Exit;
		}

		for( strPos1++; *strPos1 == ' ' || *strPos1 == '\t'; strPos1++);
		
		if( strPos2-strPos1 > MAX_SMALL_BUFFER_SIZE)
		{
			rc = RC_SET( FERR_CONV_DEST_OVERFLOW);
			goto Exit;
		}
		
		f_strncpy( uTD->folder, strPos1, strPos2-strPos1);
		uTD->folder[ strPos2 - strPos1] = '\0';

		// Get the ATTRIBUTES
		
		strPos1 = f_strchr( (const char *)strPos1, ':');
		strPos2 = f_strchr( (const char *)strPos1, '\n');
		
		if( !strPos1 || !strPos2)
		{
			rc = RC_SET( FERR_FAILURE);
			goto Exit;
		}

		for( strPos1++;*strPos1 == ' ' || *strPos1 == '\t';strPos1++);
		
		if( strPos2-strPos1 > MAX_SMALL_BUFFER_SIZE)
		{
			rc = RC_SET( FERR_FAILURE);
			goto Exit;
		}
		
		f_strncpy( uTD->attrs, strPos1, strPos2-strPos1);
		uTD->attrs[strPos2-strPos1] = '\0';

		// Get the CSVFILE
		
		strPos1 = f_strchr( (const char *)strPos1, ':');
		strPos2 = f_strchr( (const char *)strPos1, '\n');
		
		// Allow for possible \r
		
		if( *( --strPos2) != '\r')
		{
			strPos2++;
		}

		if( !strPos1 || !strPos2)
		{
			rc = RC_SET( FERR_FAILURE);
			goto Exit;
		}

		for( strPos1++;*strPos1 == ' ' || *strPos1 == '\t';strPos1++);

		if( strPos2-strPos1 > MAX_SMALL_BUFFER_SIZE)
		{
			rc = RC_SET( FERR_FAILURE);
			goto Exit;
		}

		f_strncpy( uTD->csvFilename, strPos1, strPos2-strPos1);
		uTD->csvFilename[ strPos2 - strPos1] = '\0';

		if( RC_BAD( rc = pFileSystem->openFile( uTD->csvFilename,
			FLM_IO_RDWR | FLM_IO_SH_DENYNONE, &pCSVFileHdl)))
		{
			if ( rc == FERR_IO_PATH_NOT_FOUND)
			{
				// Create the file and write the header
				
				if( RC_BAD( rc = f_filecat( uTD->csvFilename, DATA_ORDER)))
				{
					goto Exit;
				}
			}
		}
		else
		{
			goto Exit;
		}
	}

Exit:

	if( pConfigFileHdl)
	{
		pConfigFileHdl->Release();
	}
	
	if( pCSVFileHdl)
	{
		pCSVFileHdl->Release();
	}
	
	if( pFileSystem)
	{
		pFileSystem->Release();
	}
	
	return( rc);
}
Exemple #3
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);
}
Exemple #4
0
/****************************************************************************
Desc:	Copy a file that is one of the files of the database.
*****************************************************************************/
FSTATIC RCODE flmCopyFile(
	IF_FileSystem *		pFileSystem,
	FLMUINT					uiStartOffset,
	FLMUINT					uiEndOffset,
	DB_COPY_INFO *			pDbCopyInfo,
	COPIED_NAME **			ppCopiedListRV,
	FLMBYTE *				pucInMemLogHdr,
	FLMBOOL					bOkToTruncate,
	STATUS_HOOK				fnStatusCallback,
	void *					UserData)
{
	RCODE				rc = FERR_OK;
	FLMBYTE *		pucBuffer = NULL;
	IF_FileHdl *	pSrcFileHdl = NULL;
	IF_FileHdl *	pDestFileHdl = NULL;
	FLMUINT			uiBufferSize = 32768;
	FLMUINT			uiBytesToRead;
	FLMUINT			uiBytesRead;
	FLMUINT			uiBytesWritten;
	FLMUINT			uiOffset;
	FLMBYTE *		pucLogHdr = NULL;
	FLMUINT			uiNewChecksum;
	FLMBOOL			bCreatedDestFile = FALSE;

	// Open the source file.

	if( RC_BAD( rc = gv_FlmSysData.pFileSystem->openFile( 
		pDbCopyInfo->szSrcFileName, gv_FlmSysData.uiFileOpenFlags, 
		&pSrcFileHdl)))
	{
		goto Exit;
	}

	// First attempt to open the destination file.  If it does
	// not exist, attempt to create it.

	if (RC_BAD( rc = gv_FlmSysData.pFileSystem->openFile( 
		pDbCopyInfo->szDestFileName, gv_FlmSysData.uiFileOpenFlags,
		&pDestFileHdl)))
	{
		if (rc != FERR_IO_PATH_NOT_FOUND &&
			 rc != FERR_IO_INVALID_PATH)
		{
			goto Exit;
		}

		if( RC_BAD( rc = gv_FlmSysData.pFileSystem->createFile( 
			pDbCopyInfo->szDestFileName, gv_FlmSysData.uiFileCreateFlags, 
			&pDestFileHdl)))
		{
			goto Exit;
		}
		bCreatedDestFile = TRUE;
	}
								
	// Allocate a buffer for reading and writing

	if( RC_BAD( rc = f_allocAlignedBuffer( uiBufferSize, &pucBuffer)))
	{
		goto Exit;
	}

	// Allocate a buffer for the log header

	if( RC_BAD( rc = f_allocAlignedBuffer( 2048, &pucLogHdr)))
	{
		goto Exit;
	}

	// If uiStartOffset is 2048, it is the special case of
	// the control file, and we are not copying the first 2K.
	// However, we need to set up the first 2K so that if
	// someone reads the first 2K, it will return them a
	// maintenance in progress error.

	if (uiStartOffset == 2048)
	{
		// Read the first 2K of the source file.

		if (RC_BAD( rc = pSrcFileHdl->read( 0, 2048, pucBuffer, &uiBytesRead)))
		{
			if (rc == FERR_IO_END_OF_FILE)
			{
				rc = FERR_OK;
			}
			else
			{
				goto Exit;
			}
		}

		// Zero out whatever part of the 2K we didn't get on the read.

		if (uiBytesRead < 2048)
		{
			f_memset( &pucBuffer[ uiBytesRead], 0, (int)(2048 - uiBytesRead));
		}

		// Attempt to read the log header from the destination file.
		// It is OK if we can't read it, because if we created the
		// destination file, these bytes may not be present.

		if( bCreatedDestFile ||
			 RC_BAD( pDestFileHdl->read( 0, 2048, pucLogHdr, &uiBytesRead)))
		{
			f_memset( pucLogHdr, 0, sizeof( 2048));
		}

		// Set the transaction ID to zero.  MUST ALSO SET THE TRANS ACTIVE FLAG
		// TO FALSE - OTHERWISE READERS WILL ATTEMPT TO DECREMENT THE
		// TRANSACTION ID AND WILL END UP WITH 0xFFFFFFFF - very bad!
		// We must use zero, because it is the only transaction ID that will not
		// appear on ANY block.

		UD2FBA( 0, &pucLogHdr[ 16 + LOG_CURR_TRANS_ID]);

		// Recalculate the log header checksum so that readers will not get a
		// checksum error.

		uiNewChecksum = lgHdrCheckSum( &pucLogHdr[ 16], FALSE);
		UW2FBA( (FLMUINT16)uiNewChecksum, &pucLogHdr[ 16 + LOG_HDR_CHECKSUM]);
		f_memcpy( &pucBuffer[ 16], &pucLogHdr[ 16], LOG_HEADER_SIZE);

		// Write this "special" first 2K into the destination file.
		// The real first 2K from the source file will be copied in
		// at a later time.

		if (RC_BAD( rc = pDestFileHdl->write( 0, 2048, 
			pucBuffer, &uiBytesWritten)))
		{
			goto Exit;
		}

		// Save the log header to the in-memory version of the log
		// header as well - if pucInMemLogHdr is NULL, it is pointing
		// to the pFile->ucLastCommittedLogHdr buffer.

		if (pucInMemLogHdr)
		{
			f_memcpy( pucInMemLogHdr, &pucLogHdr[ 16], LOG_HEADER_SIZE);
		}
	}

	// Read from source file until we hit EOF in the file or
	// we hit the end offset.

	uiOffset = uiStartOffset;
	for (;;)
	{
		uiBytesToRead = (FLMUINT)((uiEndOffset - uiOffset >=
											uiBufferSize)
										 ? uiBufferSize
										 : (FLMUINT)(uiEndOffset - uiOffset));

		// Read data from source file.

		if (RC_BAD( rc = pSrcFileHdl->read( uiOffset, uiBytesToRead,
									pucBuffer, &uiBytesRead)))
		{
			if (rc == FERR_IO_END_OF_FILE)
			{
				rc = FERR_OK;
				if (!uiBytesRead)
				{
					break;
				}
			}
			else
			{
				goto Exit;
			}
		}

		// Write data to destination file.

		if (RC_BAD( rc = pDestFileHdl->write( uiOffset,
									uiBytesRead, pucBuffer, &uiBytesWritten)))
		{
			goto Exit;
		}

		// See if we wrote out the buffer that has the log header
		// If so, we need to copy it back to the in-memory log
		// header.

		if ((pucInMemLogHdr) &&
			 (uiOffset <= 16) &&
			 (uiOffset + uiBytesWritten >= 16 + LOG_HEADER_SIZE))
		{
			f_memcpy( pucInMemLogHdr, &pucBuffer[ 16 - uiOffset],
								LOG_HEADER_SIZE);
		}

		uiOffset += uiBytesWritten;

		// Do callback to report progress.

		if (fnStatusCallback)
		{
			pDbCopyInfo->ui64BytesCopied += (FLMUINT64)uiBytesWritten;
			if (RC_BAD( rc = (*fnStatusCallback)( FLM_DB_COPY_STATUS,
										(void *)pDbCopyInfo,
										(void *)0, UserData)))
			{
				goto Exit;
			}
			pDbCopyInfo->bNewSrcFile = FALSE;
		}

		// Quit once we reach the end offset or we read fewer bytes
		// than we asked for.

		if (uiOffset >= uiEndOffset || uiBytesRead < uiBytesToRead)
		{
			break;
		}
	}

	// If we overwrote the destination file, as opposed to creating
	// it, truncate it in case it was larger than the number of
	// bytes we actually copied.

	if (!bCreatedDestFile && bOkToTruncate)
	{
		if (RC_BAD( rc = pDestFileHdl->truncateFile( uiOffset)))
		{
			goto Exit;
		}
	}

	// If the copy succeeded, add the destination name to a list
	// of destination files.  This is done so we can clean up
	// copied files if we fail somewhere in the overall database
	// copy.

	if (ppCopiedListRV)
	{
		COPIED_NAME *	pCopyName;

		if( RC_BAD( rc = f_alloc( 
			(FLMUINT)sizeof( COPIED_NAME), &pCopyName)))
		{
			goto Exit;
		}
		f_strcpy( pCopyName->szPath, pDbCopyInfo->szDestFileName);
		pCopyName->pNext = *ppCopiedListRV;
		*ppCopiedListRV = pCopyName;
	}

Exit:

	if( pucBuffer)
	{
		f_freeAlignedBuffer( &pucBuffer);
	}

	if( pucLogHdr)
	{
		f_freeAlignedBuffer( &pucLogHdr);
	}

	if( pSrcFileHdl)
	{
		pSrcFileHdl->Release();
	}

	if( pDestFileHdl)
	{
		pDestFileHdl->flush();
		pDestFileHdl->Release();
	}

	// Attempt to delete the destination file if
	// we didn't successfully copy it.

	if( RC_BAD( rc))
	{
		(void)pFileSystem->deleteFile( pDbCopyInfo->szDestFileName);
	}

	return( rc);
}