Пример #1
0
/***************************************************************************
Desc:	Do binary comparison.
*****************************************************************************/
FINLINE FLMINT ixKeyCompareBinary(
	const void *	pvData1,
	FLMUINT			uiLen1,
	const void *	pvData2,
	FLMUINT			uiLen2,
	FLMBOOL			bSortAscending)
{
	FLMINT			iCompare;
	
	if (uiLen1 > uiLen2)
	{
		if ((iCompare = f_memcmp( pvData1, pvData2, uiLen2)) >= 0)
		{
			return( bSortAscending ? 1 : -1);
		}
		else
		{
			return( bSortAscending ? -1 : 1);
		}
	}
	else if (uiLen1 < uiLen2)
	{
		if ((iCompare = f_memcmp( pvData1, pvData2, uiLen1)) <= 0)
		{
			return( bSortAscending ? -1 : 1);
		}
		else
		{
			return( bSortAscending ? 1 : -1);
		}
	}
	else
	{
		if ((iCompare = f_memcmp( pvData1, pvData2, uiLen1)) != 0)
		{
			if (iCompare < 0)
			{
				return( bSortAscending ? -1 : 1);
			}
			else
			{
				return( bSortAscending ? 1 : -1);
			}
		}
	}
	
	return( 0);
}
Пример #2
0
/***************************************************************************
Desc:	This routine verifies that the header is a real FLAIM header.
		It will also change the endian-ness if need be.  This should always
		be called immediately after reading a header from disk.
*****************************************************************************/
FSTATIC RCODE verifyDbHdr(
	XFLM_DB_HDR *	pDbHdr
	)
{
	RCODE			rc = NE_XFLM_OK;
	FLMUINT		uiLen;
	FLMUINT32	ui32CRC;

	// Calculate the checksum before doing any conversions.

	ui32CRC = calcDbHdrCRC( pDbHdr);

	// Convert the header to native platform format if necessary.

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

	// Check the signature.

	uiLen = f_strlen( XFLM_DB_SIGNATURE);
	if (f_memcmp( pDbHdr->szSignature, XFLM_DB_SIGNATURE, uiLen) != 0)
	{
		rc = RC_SET( NE_XFLM_NOT_FLAIM);
		goto Exit;
	}

	// See if the database version is OK.

	switch (pDbHdr->ui32DbVersion)
	{
		case XFLM_VER_5_12:
			break;
		default:
			if (pDbHdr->ui32DbVersion > XFLM_CURRENT_VERSION_NUM)
			{
				rc = RC_SET( NE_XFLM_NEWER_FLAIM);
			}
			else
			{
				rc = RC_SET( NE_XFLM_UNSUPPORTED_VERSION);
			}
			goto Exit;
	}

	// Validate the checksum

	if (ui32CRC != pDbHdr->ui32HdrCRC)
	{
		rc = RC_SET( NE_XFLM_HDR_CRC);
		goto Exit;
	}

Exit:

	return( rc);
}
Пример #3
0
/****************************************************************************
Desc:	Compare function used to compare key data
****************************************************************************/
FINLINE FLMBOOL krefIsKeyDataEqual(
	KREF_ENTRY * 	pKrefA,
	KREF_ENTRY *	pKrefB)
{
	if( pKrefA->uiDataLen != pKrefB->uiDataLen)
	{
		return( FALSE);
	}
	
	if( pKrefA->uiDataLen)
	{
		if( f_memcmp( (FLMBYTE *)(&pKrefA [1]) +
												pKrefA->ui16KeyLen + 1,
									(FLMBYTE *)(&pKrefB [1]) +
												pKrefB->ui16KeyLen + 1,
									pKrefA->uiDataLen) != 0)
		{
			return( FALSE);
		}
	}
	
	return( TRUE);
}
/****************************************************************************
Desc:	Search a single block tree.  Position for get* or for insert.
		Do a binary search on all of the entries to find a match.
		If no match then position to the entry where an insert
		will take place.
****************************************************************************/
RCODE F_BtreeBlk::searchEntry(
    void *		pvEntry,
    FLMUINT *	puiChildAddr,
    void *		pvFoundEntry)
{
    RCODE			rc = RC_SET( NE_FLM_NOT_FOUND);
    FLMUINT		uiLow;
    FLMUINT		uiMid;
    FLMUINT		uiHigh;
    FLMUINT		uiTblSize;
    FLMINT		iCompare;

    // check for zero entries.

    if (!entryCount())
    {
        uiMid = 0;
        goto Exit;
    }
    uiHigh = uiTblSize = entryCount() - 1;
    uiLow = 0;
    for(;;)
    {
        uiMid = (uiLow + uiHigh) >> 1;		// (uiLow + uiHigh) / 2

        // Use compare routine

        if (m_fnCompare)
        {
            iCompare = m_fnCompare( pvEntry, ENTRY_POS( uiMid), m_pvUserData);
        }
        else
        {
            iCompare = f_memcmp( pvEntry, ENTRY_POS( uiMid), m_uiEntrySize);
        }

        if (iCompare == 0)
        {
            if (pvFoundEntry)
            {
                f_memcpy( pvFoundEntry, ENTRY_POS( uiMid), m_uiEntrySize);
            }
            rc = NE_FLM_OK;
            goto Exit;
        }

        // Check if we are done - where wLow equals uiHigh or mid is at end.

        if (iCompare < 0)
        {
            if (uiMid == uiLow || uiLow == uiHigh)
            {
                break;
            }
            uiHigh = uiMid - 1;					// Too high
        }
        else
        {
            if (uiMid == uiHigh || uiLow == uiHigh)
            {

                // Go up one for the correct position?

                uiMid++;
                break;
            }
            uiLow = uiMid + 1;					// Too low
        }
    }

Exit:

    m_uiPosition = uiMid;
    if (puiChildAddr && blkType() != ACCESS_BTREE_LEAF)
    {
        if (uiMid == entryCount())
        {
            *puiChildAddr = lemBlk();
        }
        else
        {
            FLMBYTE *	pucChildAddr = ENTRY_POS(uiMid) + m_uiEntrySize;
            *puiChildAddr = (FLMUINT)FB2UD( pucChildAddr);
        }
    }
    return( rc);
}
/****************************************************************************
Desc:
****************************************************************************/
RCODE IRegressionTestImpl::truncatedValueFromStoreDefectTest( void)
{
	RCODE					rc = NE_XFLM_OK;
	FLMBOOL				bTransBegun = FALSE;
	FLMBOOL				bDibCreated = FALSE;
	FLMUINT				uiRootId = 0;
	FLMUINT				uiTextValId = 0;
	FLMUINT				uiNumVal1Id = 0;
	FLMUINT				uiNumVal2Id = 0;
	FLMUINT				uiNumVal3Id = 0;
	FLMUINT				uiBinValId = 0;
	FLMBYTE				pucBinVal[] = BIN_VAL;
	FLMUINT64			ui64RootId = 0;
	FLMUINT				uiNameId = 0;
	IF_DOMNode *		pRootNode = NULL;
	IF_DOMNode *		pValNode = NULL;

	beginTest( 	
		"Truncated Value From Store Defect Test",
		"Make sure values make it back from disk intact",
		"Add values to database/close database/open database/verify values",
		"");

	if ( RC_BAD( rc = initCleanTestState( DB_NAME_STR)))
	{
		goto Exit;
	}
	bDibCreated = TRUE;

	if ( RC_BAD( rc = m_pDb->transBegin( XFLM_UPDATE_TRANS)))
	{
		MAKE_ERROR_STRING( "transBegin failed", m_szDetails, rc);
		goto Exit;
	}
	bTransBegun = TRUE;

	if ( RC_BAD( rc = m_pDb->createElementDef(
		NULL,
		"root",
		XFLM_NODATA_TYPE,
		&uiRootId)))
	{
		MAKE_ERROR_STRING( "createElementDef failed", m_szDetails, rc);
		goto Exit;
	}

	if ( RC_BAD( rc = m_pDb->createElementDef(
		NULL,
		"text_val",
		XFLM_TEXT_TYPE,
		&uiTextValId)))
	{
		MAKE_ERROR_STRING( "createElementDef failed", m_szDetails, rc);
		goto Exit;
	}

	if ( RC_BAD( rc = m_pDb->createElementDef(
		NULL,
		"uint64_val",
		XFLM_NUMBER_TYPE,
		&uiNumVal1Id)))
	{
		MAKE_ERROR_STRING( "createElementDef failed", m_szDetails, rc);
		goto Exit;
	}

	if ( RC_BAD( rc = m_pDb->createElementDef(
		NULL,
		"int64_val",
		XFLM_NUMBER_TYPE,
		&uiNumVal2Id)))
	{
		MAKE_ERROR_STRING( "createElementDef failed", m_szDetails, rc);
		goto Exit;
	}

	if ( RC_BAD( rc = m_pDb->createElementDef(
		NULL,
		"uint_val",
		XFLM_NUMBER_TYPE,
		&uiNumVal3Id)))
	{
		MAKE_ERROR_STRING( "createElementDef failed", m_szDetails, rc);
		goto Exit;
	}

	if ( RC_BAD( rc = m_pDb->createElementDef(
		NULL,
		"bin_val",
		XFLM_BINARY_TYPE,
		&uiBinValId)))
	{
		MAKE_ERROR_STRING( "createElementDef failed", m_szDetails, rc);
		goto Exit;
	}

	if ( RC_BAD( rc = m_pDb->createRootElement(
		XFLM_DATA_COLLECTION,
		uiRootId,
		&pRootNode)))
	{
		MAKE_ERROR_STRING( "createRootElement failed.", m_szDetails, rc);
		goto Exit;
	}
	
	if( RC_BAD( rc = pRootNode->getNodeId( m_pDb, &ui64RootId)))
	{
		goto Exit;
	}

	if ( RC_BAD( rc = pRootNode->createNode( m_pDb,
		ELEMENT_NODE, uiTextValId, XFLM_FIRST_CHILD,	&pValNode)))
	{
		MAKE_ERROR_STRING( "createNode failed.", m_szDetails, rc);
		goto Exit;
	}

	if ( RC_BAD( rc = pValNode->setUTF8( m_pDb, 
		(FLMBYTE *)TEXT_VAL, f_strlen( TEXT_VAL))))
	{
		MAKE_ERROR_STRING( "setUTF8 failed", m_szDetails, rc);
		goto Exit;
	}

	if ( RC_BAD( rc = pRootNode->createNode( m_pDb,
		ELEMENT_NODE, uiNumVal1Id, XFLM_FIRST_CHILD,	&pValNode)))
	{
		MAKE_ERROR_STRING( "createNode failed.", m_szDetails, rc);
		goto Exit;
	}

	if ( RC_BAD( rc = pValNode->setUINT64( m_pDb, UINT64_VAL)))
	{
		MAKE_ERROR_STRING( "setUINT64 failed", m_szDetails, rc);
		goto Exit;
	}

	if ( RC_BAD( rc = pRootNode->createNode( m_pDb,
		ELEMENT_NODE, uiNumVal2Id, XFLM_FIRST_CHILD,	&pValNode)))
	{
		MAKE_ERROR_STRING( "createNode failed.", m_szDetails, rc);
		goto Exit;
	}

	if ( RC_BAD( rc = pValNode->setINT64( m_pDb, INT64_VAL)))
	{
		MAKE_ERROR_STRING( "setINT64 failed", m_szDetails, rc);
		goto Exit;
	}

	if ( RC_BAD( rc = pRootNode->createNode( m_pDb,
		ELEMENT_NODE, uiNumVal3Id, XFLM_FIRST_CHILD,	&pValNode)))
	{
		MAKE_ERROR_STRING( "createNode failed.", m_szDetails, rc);
		goto Exit;
	}

	if ( RC_BAD( rc = pValNode->setUINT( m_pDb, UINT_VAL)))
	{
		MAKE_ERROR_STRING( "setUINT failed", m_szDetails, rc);
		goto Exit;
	}

	if ( RC_BAD( rc = pRootNode->createNode( m_pDb,
		ELEMENT_NODE, uiBinValId, XFLM_FIRST_CHILD,	&pValNode)))
	{
		MAKE_ERROR_STRING( "createNode failed.", m_szDetails, rc);
		goto Exit;
	}

	if ( RC_BAD( rc = pValNode->setBinary( m_pDb, pucBinVal, BIN_VAL_LEN, TRUE)))
	{
		MAKE_ERROR_STRING( "setBinary failed", m_szDetails, rc);
		goto Exit;
	}

	// close the database to force the values to disk

	if ( RC_BAD( rc = m_pDb->transCommit()))
	{
		goto Exit;
	}
	bTransBegun = FALSE;

	pRootNode->Release();
	pRootNode = NULL;
	pValNode->Release();
	pValNode = NULL;
	m_pDb->Release();
	m_pDb = NULL;

	if( RC_BAD( rc = m_pDbSystem->dbOpen( DB_NAME_STR, NULL, NULL, 
		NULL, FALSE, &m_pDb)))
	{
		MAKE_ERROR_STRING( "dbOpen failed", m_szDetails, rc);
		goto Exit;
	}

	if ( RC_BAD( rc = m_pDb->transBegin( XFLM_READ_TRANS)))
	{
		MAKE_ERROR_STRING( "transBegin failed", m_szDetails, rc);
		goto Exit;
	}
	bTransBegun = TRUE;

	if ( RC_BAD( rc = m_pDb->getNode(
		XFLM_DATA_COLLECTION, ui64RootId, &pRootNode)))
	{
		MAKE_ERROR_STRING( "getNode failed", m_szDetails, rc);
		goto Exit;
	}

	if ( RC_BAD( rc = pRootNode->getFirstChild(
		m_pDb, &pValNode)))
	{
		MAKE_ERROR_STRING( "getFirstChild failed", m_szDetails, rc);
		goto Exit;
	}

	for(;;)
	{
		if ( RC_BAD( rc = pValNode->getNameId( m_pDb, &uiNameId)))
		{
			MAKE_ERROR_STRING( "getNameId failed", m_szDetails, rc);
			goto Exit;
		}

		if ( uiNameId == uiTextValId)
		{
			char szTemp[100];

			if ( RC_BAD( rc = pValNode->getUTF8( 
				m_pDb, (FLMBYTE *)szTemp, sizeof( szTemp), 
				0, sizeof(szTemp) -1)))
			{
				MAKE_ERROR_STRING( "getUTF8 failed", m_szDetails, rc);
				goto Exit;
			}

			if ( f_strcmp( szTemp, TEXT_VAL) != 0)
			{
				rc = RC_SET( NE_XFLM_DATA_ERROR);
				MAKE_ERROR_STRING( "Unexpected text value found", m_szDetails, rc);
				goto Exit;
			}
			// flag this name id as visited
			uiTextValId = 0;
		}
		else if ( uiNameId == uiNumVal1Id)
		{
			FLMUINT64	ui64Temp;

			if ( RC_BAD( rc = pValNode->getUINT64( m_pDb, &ui64Temp)))
			{
				MAKE_ERROR_STRING( "getUINT64 Failed", m_szDetails, rc);
				goto Exit;
			}

			if ( ui64Temp != UINT64_VAL)
			{
				rc = RC_SET( NE_XFLM_DATA_ERROR);
				MAKE_ERROR_STRING( "Unexpected uint64 value found", m_szDetails, rc);
				goto Exit;
			}
			uiNumVal1Id = 0;
		}
		else if ( uiNameId == uiNumVal2Id)
		{
			FLMINT64	i64Temp;

			if ( RC_BAD( rc = pValNode->getINT64( m_pDb, &i64Temp)))
			{
				goto Exit;
			}

			if ( i64Temp != INT64_VAL)
			{
				rc = RC_SET( NE_XFLM_DATA_ERROR);
				MAKE_ERROR_STRING( "Unexpected int64 value found", m_szDetails, rc);
				goto Exit;
			}
			uiNumVal2Id = 0;
		}
		else if ( uiNameId == uiNumVal3Id)
		{
			FLMUINT	uiTemp;

			if ( RC_BAD( rc = pValNode->getUINT( m_pDb, &uiTemp)))
			{
				MAKE_ERROR_STRING( "getUINT failed", m_szDetails, rc);
				goto Exit;
			}

			if ( uiTemp != UINT_VAL)
			{
				rc = RC_SET( NE_XFLM_DATA_ERROR);
				MAKE_ERROR_STRING( "Unexpected uint value found", m_szDetails, rc);
				goto Exit;
			}
			uiNumVal3Id = 0;
		}
		else if ( uiNameId == uiBinValId)
		{
			FLMBYTE	pucTemp[BIN_VAL_LEN];
			FLMUINT	uiTmp;

			if ( RC_BAD( rc = pValNode->getBinary( 
				m_pDb,
				pucTemp,
				0,
				sizeof(pucTemp),
				&uiTmp)))
			{
				MAKE_FLM_ERROR_STRING( "getBinary failed.", m_szDetails, rc);
				goto Exit;
			}

			if ( uiTmp != BIN_VAL_LEN ||
				f_memcmp( pucTemp, pucBinVal, uiTmp) != 0)
			{
				rc = RC_SET( NE_XFLM_DATA_ERROR);
				MAKE_ERROR_STRING( "Unexpected binary value found", m_szDetails, rc);
				goto Exit;
			}
			uiBinValId = 0;
		}
		else
		{
			rc = RC_SET( NE_XFLM_DATA_ERROR);
			MAKE_ERROR_STRING( "Unexpected node found", m_szDetails, rc);
			goto Exit;
		}

		if ( RC_BAD( rc = pValNode->getNextSibling( m_pDb, &pValNode)))
		{
			if ( rc != NE_XFLM_DOM_NODE_NOT_FOUND || uiTextValId ||
				uiNumVal1Id || uiNumVal2Id || uiNumVal3Id || uiBinValId)
			{
				rc = RC_SET( NE_XFLM_DATA_ERROR);
				MAKE_ERROR_STRING( "Node not found", m_szDetails, rc);
				goto Exit;
			}
			else
			{
				rc = NE_XFLM_OK;
				break;
			}
		}
	}

	endTest("PASS");

Exit:

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

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

	if( RC_BAD( rc))
	{
		endTest("FAIL");
	}

	if( bTransBegun)
	{
		if( RC_OK( rc))
		{
			rc = m_pDb->transCommit();
		}
		else
		{
			m_pDb->transAbort();
		}
	}

	shutdownTestState( DB_NAME_STR, bDibCreated);
	return( rc);
}
Пример #6
0
/***************************************************************************
Desc:	Program entry point (main)
****************************************************************************/
extern "C" int main(
	int,			// iArgC,
	char **		// ppucArgV
	)
{
	RCODE						rc = NE_XFLM_OK;
	FLMBYTE					ucMsgBuf[ 200];
	XFLM_CREATE_OPTS		createOpts;
	IF_DbSystem *			pDbSystem = NULL;
	IF_Db *					pDb = NULL;
	IF_Backup *				pBackup = NULL;
	IF_DOMNode *			pTmpNode = NULL;
	FLMUINT					uiMusicElementDef=0;
	FLMUINT					uiCdElementDef=0;
	FLMUINT					uiTitleElementDef=0;
	FLMUINT					uiArtistElementDef=0;
	FLMUINT					uiTracksElementDef=0;
	FLMUINT					uiNoAttrDef=0;
	FLMUINT					uiTitleAttrDef=0;
	FLMUINT					uiCollectionDef=0;
	FLMBOOL					bTranStarted = FALSE;
	IF_DOMNode *			pCdChild = NULL;
	IF_DOMNode *			pCdElement = NULL;
	IF_DOMNode *			pMusicElement = NULL;
	IF_DOMNode *			pCdAttr = NULL;
	IF_DOMNode *			pTrackNode = NULL;
	IF_Query *				pQuery = NULL;
	IF_PosIStream	*		pPosIStream = NULL;
	IF_PosIStream *		pIStream = NULL;
	FLMUINT					uiIndex = 1;
	FLMBYTE					ucUntilKeyBuf[ XFLM_MAX_KEY_SIZE];
	FLMUINT					uiUntilKeyLen;
	FLMBYTE					ucCurrentKeyBuf[ XFLM_MAX_KEY_SIZE];
	FLMUINT					uiCurrentKeyLen;
	FLMUINT64				ui64DocId;
	char						ucTitle[ 200];
	FLMUINT					uiTitleLen;
	char *					ppszPath[] = 
				{
					"7001e10c.xml",
					"70028663.xml",
					"70037c08.xml",
					"70040b08.xml",
					"70044808.xml",
					"70045109.xml",
					"70045e09.xml",
					"70046709.xml",
					"7004920a.xml",
					""
				};
	FLMUINT					uiLoop;
	IF_DataVector *		pFromKeyV = NULL;
	IF_DataVector *		pUntilKeyV = NULL;
	const char *			pszQueryString = "/music/cd/tracks[@title~=\"we our in luv\"]";
	const char *			pszIndex =
		"<xflaim:Index "
			"xmlns:xflaim=\"http://www.novell.com/XMLDatabase/Schema\" "
			"xflaim:name=\"title_IX\">"
			"<xflaim:ElementComponent "
				"xflaim:name=\"title\" "
				"xflaim:IndexOn=\"value\" "
				"xflaim:KeyComponent=\"1\"/>"
		"</xflaim:Index>";

	// Allocate a DbSystem object

	if( RC_BAD( rc = FlmAllocDbSystem( &pDbSystem)))
	{
		goto Exit;
	}

	// Create the database.  This code will remove the database first if it
	// exists.  Once removed, it will try to create it.  If that fails for
	// any reason other than the database already exists, it will exit.

RetryCreate:

	f_memset( &createOpts, 0, sizeof( XFLM_CREATE_OPTS));
	
	if( RC_BAD( rc = pDbSystem->dbCreate( DB_NAME_STR, NULL, NULL, NULL,
			NULL, &createOpts, &pDb)))
	{
		if( RC_BAD( rc == NE_XFLM_FILE_EXISTS))
		{
			if( RC_BAD( rc = pDbSystem->dbRemove( DB_NAME_STR, NULL, NULL, TRUE)))
			{
				goto Exit;
			}

			goto RetryCreate;
		}
		else
		{
			goto Exit;
		}
	}

	// Start an update transaction.  All access to the database should
	// be done within the confines of a transaction.  When changes are being
	// made to the database, an UPDATE transaction is required.  It is best to
	// keep transactions small if possible.

	if( RC_BAD( rc = pDb->transBegin( XFLM_UPDATE_TRANS, FLM_NO_TIMEOUT)))
	{
		goto Exit;
	}
	bTranStarted = TRUE;

	// Let's create a document to demonstrate how we use the DOM...
	// Our document will catalog a music CD.  It will look like:

	// <music>
	// 	<cd>
	// 		<title>We Are In Love</title>
	// 		<artist>Harry Connick Jr.</artist>
	// 		<tracks no="1" title="We Are In Love"/>
	// 		<tracks no="2" title="Only 'Cause I Don't Have You"/>
	// 	</cd>
	// </music>

	// To accomplish this, we must define the elements of the document and a new
	// collection to store the document in.

	// Create some element definitions for our document.
	// Create the "music" element definition.

	if( RC_BAD( rc = pDb->createElementDef( NULL, "music", 
		XFLM_NODATA_TYPE, &uiMusicElementDef)))
	{
		goto Exit;
	}

	// Create the "cd" element definition.

	if( RC_BAD( rc = pDb->createElementDef( NULL, "cd",
		XFLM_NODATA_TYPE, &uiCdElementDef)))
	{
		goto Exit;
	}

	// Create the "title" element definition.

	if( RC_BAD( rc = pDb->createElementDef( NULL, "title",
		XFLM_TEXT_TYPE, &uiTitleElementDef)))
	{
		goto Exit;
	}

	// Create the "artist" element definition.

	if( RC_BAD( rc = pDb->createElementDef( NULL, "artist",
		XFLM_TEXT_TYPE, &uiArtistElementDef)))
	{
		goto Exit;
	}

	// Create the "tracks" element definition.

	if( RC_BAD( rc = pDb->createElementDef( NULL, "tracks",
		XFLM_NODATA_TYPE, &uiTracksElementDef)))
	{
		goto Exit;
	}

	// Create the "no" attribute definition.

	if( RC_BAD( rc = pDb->createAttributeDef( NULL, "no",
		XFLM_NUMBER_TYPE, &uiNoAttrDef)))
	{
		goto Exit;
	}

	// Create the "title" attribute definition.

	if( RC_BAD( rc = pDb->createAttributeDef( NULL, "title",
		XFLM_TEXT_TYPE, &uiTitleAttrDef)))
	{
		goto Exit;
	}

	// Create our special music collection for storing music stuff.

	if( RC_BAD( rc = pDb->createCollectionDef( "Music Collection",
		&uiCollectionDef)))
	{
		goto Exit;
	}

	// We now have all of the definitions we need to build our document.
	// Lets first create a new document, followed by its members...

	// Create the "music" root element

	if( RC_BAD( rc = pDb->createRootElement( uiCollectionDef, uiMusicElementDef,
		&pMusicElement)))
	{
		goto Exit;
	}

	// Create the "cd" element

	if( RC_BAD( rc = pMusicElement->createNode( pDb, ELEMENT_NODE,
		uiCdElementDef, XFLM_FIRST_CHILD, &pCdElement)))
	{
		goto Exit;
	}
	
	// Create the "title" element

	if( RC_BAD( rc = pCdElement->createNode( pDb, ELEMENT_NODE,
		uiTitleElementDef, XFLM_FIRST_CHILD, &pCdChild)))
	{
		goto Exit;
	}

	// Set the value for the title.

	if (RC_BAD( rc = pCdChild->setUTF8( pDb, (FLMBYTE *)"We Are In Love")))
	{
		goto Exit;
	}
	
	// Create the "artist" element

	if( RC_BAD( rc = pCdElement->createNode( pDb, ELEMENT_NODE,
		uiArtistElementDef, XFLM_LAST_CHILD, &pCdChild)))
	{
		goto Exit;
	}

	// Set the value for the title.

	if (RC_BAD( rc = pCdChild->setUTF8( pDb, (FLMBYTE *)"Harry Connick Jr.")))
	{
		goto Exit;
	}
	
	// Create the first "tracks" element

	if( RC_BAD( rc = pCdElement->createNode( pDb, ELEMENT_NODE,
		uiTracksElementDef, XFLM_LAST_CHILD, &pCdChild)))
	{
		goto Exit;
	}

	// Create the "no." attribute, then the "title" attribute.
	
	if (RC_BAD( rc = pCdChild->createAttribute( pDb, uiNoAttrDef, &pCdAttr)))
	{
		goto Exit;
	}

	if (RC_BAD( rc = pCdAttr->setUINT( pDb, (FLMUINT)1)))
	{
		goto Exit;
	}

	if (RC_BAD( rc = pCdChild->createAttribute( pDb, uiTitleAttrDef, &pCdAttr)))
	{
		goto Exit;
	}

	if (RC_BAD( rc = pCdAttr->setUTF8( pDb, (FLMBYTE *)"We Are In Love")))
	{
		goto Exit;
	}

	// Create the next "tracks" element

	if( RC_BAD( rc = pCdElement->createNode( pDb, ELEMENT_NODE,
		uiTracksElementDef, XFLM_LAST_CHILD, &pCdChild)))
	{
		goto Exit;
	}

	// An alternate way to create the attributes and set their values is to use
	// the parent element to set the attribute values.

	// Create the two attributes.

	if (RC_BAD( rc = pCdChild->createAttribute( pDb, uiNoAttrDef, &pCdAttr)))
	{
		goto Exit;
	}

	if (RC_BAD( rc = pCdChild->createAttribute( pDb, uiTitleAttrDef, &pCdAttr)))
	{
		goto Exit;
	}

	// Using the parent of the attributes, set their values by specifying
	// which attribute to set.

	if (RC_BAD( rc = pCdChild->setAttributeValueUINT( pDb, uiNoAttrDef,
		(FLMUINT)2)))
	{
		goto Exit;
	}

	if (RC_BAD( rc = pCdChild->setAttributeValueUTF8(
		pDb, uiTitleAttrDef, (FLMBYTE *)"Only 'Cause I Don't Have You")))
	{
		goto Exit;
	}

	// It is always good practice to call documentDone whenever updates to a
	// document are completed.

	if (RC_BAD( rc = pDb->documentDone( pMusicElement)))
	{
		goto Exit;
	}

	// Commit the transaction

	if( RC_BAD( rc = pDb->transCommit()))
	{
		goto Exit;
	}
	bTranStarted= FALSE;

	// Now we want to read back our document, and display it for all 
	// the world to see...:^)

	// Start a read transaction

	if( RC_BAD( rc = pDb->transBegin( XFLM_READ_TRANS, 0)))
	{
		goto Exit;
	}
	bTranStarted = TRUE;

	// Read the nodes.  Start with the document node.

	if( RC_BAD( rc = pDb->getFirstDocument( uiCollectionDef, &pTmpNode)))
	{
		goto Exit;
	}

	// printDocument is a simple function that walks through the document
	// and displays it, node by node as an XML document.  It assumes the 
	// node passed in is the root node.  If it is not, then the display will
	// look a bit odd, as you will see later in this sample program.

	if (RC_BAD( rc = printDocument( pDb, pTmpNode)))
	{
		goto Exit;
	}

	// Commit the transaction

	if( RC_BAD( rc = pDb->transCommit()))
	{
		goto Exit;
	}
	bTranStarted = FALSE;

	// Start an update transaction

	if( RC_BAD( rc = pDb->transBegin( XFLM_READ_TRANS, 0)))
	{
		goto Exit;
	}
	bTranStarted = TRUE;

	// Let's do a query on this document...  Our query (above) is
	// deliberately miss-spelling some of the words.  It is looking for
	// the music "tracks" with the title "We Are In Love".
	// The syntax ~= means approximately equals, and is a "sounds like" 
	// search.

	if (RC_BAD( rc = pDbSystem->createIFQuery( &pQuery)))
	{
		goto Exit;
	}

	if (RC_BAD( rc = pQuery->setCollection( uiCollectionDef)))
	{
		goto Exit;
	}

	if (RC_BAD( rc = pQuery->setupQueryExpr( pDb, pszQueryString)))
	{
		goto Exit;
	}

	if (RC_BAD( rc = pQuery->getFirst( pDb, &pTrackNode)))
	{
		goto Exit;
	}

	printMessage( "Query:");
	printMessage( pszQueryString);

	// This will pring the tracks node, followed by all of the closing parent
	// nodes.

	if (RC_BAD( rc = printDocument( pDb, pTrackNode)))
	{
		goto Exit;
	}

	pQuery->Release();
	pQuery = NULL;

	// Commit the transaction

	if( RC_BAD( rc = pDb->transCommit()))
	{
		goto Exit;
	}
	bTranStarted = FALSE;

	// Let's create an index to make searching easier.  An index is essentially
	// just another XML document to XFlaim, however it is created in the dictionary
	// collection rather than in a data collection.  There are two ways to create
	// a document in XFlaim.  One way (demonstrated above) is to create each node
	// of the document, one at a time.  The other is to import the document.
	// Creating the index will demonstrate importing the document.  Our
	// index definition is shown as follows:

	// <xflaim:Index
	// 	xmlns:xflaim="http://www.novell.com/XMLDatabase/Schema"
	// 	xflaim:name="title_IX">
	// 	<xflaim:ElementComponent
	// 		xflaim:name="title"
	// 		xflaim:DictNum="1"
	// 		xflaim:IndexOn="value"/>
	// </xflaim:Index>"

	// For our purposes, we will create a local variable (pszIndex) which
	// holds the index document.  We will import that using the importDocument
	// method of the pDb object.

	// Import the index...
	// We first need to create a BufferIStream object to stream the document
	// from...
	// Start an update transaction

	if( RC_BAD( rc = pDb->transBegin( XFLM_UPDATE_TRANS, FLM_NO_TIMEOUT)))
	{
		goto Exit;
	}
	bTranStarted = TRUE;

	if ( RC_BAD( rc = pDbSystem->openBufferIStream( pszIndex, 
		f_strlen( pszIndex), &pPosIStream)))
	{
		goto Exit;
	}

	if ( RC_BAD( rc = pDb->import( pPosIStream, XFLM_DICT_COLLECTION)))
	{
		goto Exit;
	}

	// Commit the transaction

	if( RC_BAD( rc = pDb->transCommit()))
	{
		goto Exit;
	}
	bTranStarted = FALSE;

	// Now, let's get some additional documents in so we can do some more
	// interesting stuff using a IF_DataVector.  The documents we are
	// interested in searching are the CD music documents.
	// They have the following format:

	// <?xml version="1.0"?>
	// <disc>
	// 	<id>00097210</id>
	// 	<length>2420</length>
	// 	<title>Frank Sinatra / Blue skies</title>
	// 	<genre>cddb/jazz</genre>
	// 	<track index="1" offset="150">blue skies</track>
	// 	.
	// 	.
	// 	.
	// </disc>

	if( RC_BAD( rc = pDb->transBegin( XFLM_UPDATE_TRANS, FLM_NO_TIMEOUT)))
	{
		goto Exit;
	}
	bTranStarted = TRUE;

	// We will first need an input file stream.

	uiLoop = 0;
	while( f_strlen( ppszPath[ uiLoop]))
	{
		if( RC_BAD( rc = pDbSystem->openFileIStream( 
			ppszPath[ uiLoop], &pIStream)))
		{
			goto Exit;
		}
		
		if( RC_BAD( rc = pDb->import( pIStream, XFLM_DATA_COLLECTION)))
		{
			goto Exit;
		}
		
		uiLoop++;
	}

	// Commit the transaction

	if( RC_BAD( rc = pDb->transCommit()))
	{
		goto Exit;
	}
	bTranStarted = FALSE;

	// Let's get some IF_DataVectors to work with.

	if( RC_BAD( rc = pDb->transBegin( XFLM_READ_TRANS, 0)))
	{
		goto Exit;
	}
	bTranStarted = TRUE;

	if (RC_BAD( rc = pDbSystem->createIFDataVector( &pFromKeyV)))
	{
		goto Exit;
	}

	if (RC_BAD( rc = pDbSystem->createIFDataVector( &pUntilKeyV)))
	{
		goto Exit;
	}

	// We need to get the index.

	// Now to search	the index above for all document titles in the index and
	// display the document Id and title for each node.  Note that the index
	// number is known to be 1.

	if (RC_BAD( rc = pDb->keyRetrieve( uiIndex, NULL, XFLM_FIRST, pFromKeyV)))
	{
		goto Exit;
	}

	if (RC_BAD( rc = pDb->keyRetrieve( uiIndex, NULL, XFLM_LAST, pUntilKeyV)))
	{
		goto Exit;
	}

	// Save the UntilKey value to compare with later.

	if (RC_BAD( rc = pUntilKeyV->outputKey( pDb, uiIndex, FALSE,
		&ucUntilKeyBuf[0], XFLM_MAX_KEY_SIZE, &uiUntilKeyLen)))
	{
		goto Exit;
	}

	for (;;)
	{
		// Display the current Document Id and the title.

		ui64DocId = pFromKeyV->getDocumentID();

		uiTitleLen = sizeof(ucTitle);
		if (RC_BAD( rc = pFromKeyV->getUTF8( 0, 
			(FLMBYTE *)&ucTitle[0], &uiTitleLen)))
		{
			goto Exit;
		}

		f_sprintf( (char *)&ucMsgBuf[0], "DocId: %"UI64FormatStr"\n%s\n",
			ui64DocId, ucTitle);
		printMessage( (char *)&ucMsgBuf[0]);

		// Check to see if this key matches the last or UntilKeyV value.

		if (RC_BAD( rc = pFromKeyV->outputKey( pDb, uiIndex, FALSE,
			&ucCurrentKeyBuf[0], XFLM_MAX_KEY_SIZE, &uiCurrentKeyLen)))
		{
			goto Exit;
		}

		if (uiCurrentKeyLen == uiUntilKeyLen)
		{
			if( f_memcmp( ucCurrentKeyBuf, ucUntilKeyBuf, uiCurrentKeyLen) == 0)
			{
				// We are done!

				break;
			}
		}

		// Get the next key.

		if (RC_BAD( rc = pDb->keyRetrieve( uiIndex, pFromKeyV,
			XFLM_EXCL, pFromKeyV)))
		{
			goto Exit;
		}
	}

	if( RC_BAD( rc = pDb->transCommit()))
	{
		goto Exit;
	}
	bTranStarted = FALSE;

	// Close the database

	pDb->Release();
	pDb = NULL;

	// Close all unused files

	if( RC_BAD( rc = pDbSystem->closeUnusedFiles( 0)))
	{
		goto Exit;
	}

	// Re-open the database

	if( RC_BAD( rc = pDbSystem->dbOpen( DB_NAME_STR, NULL, 
		NULL, NULL, FALSE, &pDb)))
	{
		goto Exit;
	}

	// Backup the database

	if( RC_BAD( rc = pDb->backupBegin( XFLM_FULL_BACKUP, XFLM_READ_TRANS,
		0, &pBackup)))
	{
		goto Exit;
	}

	if( RC_BAD( rc = pBackup->backup( BACKUP_NAME_STR, NULL, NULL, NULL, NULL)))
	{
		goto Exit;
	}

	if (RC_BAD( rc = pBackup->endBackup()))
	{
		goto Exit;
	}

	pBackup->Release();
	pBackup = NULL;

	// Close the database again

	pDb->Release();
	pDb = NULL;

	if( RC_BAD( rc = pDbSystem->closeUnusedFiles( 0)))
	{
		goto Exit;
	}

	// Remove the database

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

	// Restore the database

	if( RC_BAD( rc = pDbSystem->dbRestore( DB_NAME_STR, NULL, NULL,
		BACKUP_NAME_STR, NULL, NULL, NULL)))
	{
		goto Exit;
	}

	// Rename the database

	if( RC_BAD( rc = pDbSystem->dbRename( DB_NAME_STR, NULL, NULL,
			NEW_NAME_STR, TRUE, NULL)))
	{
		goto Exit;
	}

	// Copy the database

	if( RC_BAD( rc = pDbSystem->dbCopy( NEW_NAME_STR, NULL, NULL,
		DB_NAME_STR, NULL, NULL, NULL)))
	{
		goto Exit;
	}

	// Remove the new database

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


Exit:

	if (bTranStarted && pDb)
	{
		(void)pDb->transAbort();
	}

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

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

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

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

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

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

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

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

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

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

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

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

	// Close the database object

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

	if( RC_BAD( rc))
	{
		f_sprintf( (char *)ucMsgBuf, "Error 0x%04X\n",
											(unsigned)rc);
		printMessage( (char *)ucMsgBuf);
	}

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

	return( 0);
}