/*************************************************************************** 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); }
/*************************************************************************** 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); }
/**************************************************************************** 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); }
/*************************************************************************** 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); }