diff options
Diffstat (limited to 'xmlhelp/source/cxxhelp/provider/db.cxx')
-rw-r--r-- | xmlhelp/source/cxxhelp/provider/db.cxx | 449 |
1 files changed, 443 insertions, 6 deletions
diff --git a/xmlhelp/source/cxxhelp/provider/db.cxx b/xmlhelp/source/cxxhelp/provider/db.cxx index ca3f63c367dd..3cc9b6168076 100644 --- a/xmlhelp/source/cxxhelp/provider/db.cxx +++ b/xmlhelp/source/cxxhelp/provider/db.cxx @@ -36,25 +36,459 @@ #include <rtl/alloc.h> #include <cstring> +#include "com/sun/star/io/XSeekable.hpp" + +#ifdef TEST_DBHELP +#include <osl/time.h>
+#endif
+ +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::io; + namespace berkeleydbproxy { //---------------------------------------------------------------------------- - namespace db_internal +namespace db_internal +{ + // static void raise_error(int dberr, const char * where); + + static inline int check_error(int dberr, const char * where) + { + (void)where; + + // if (dberr) raise_error(dberr,where); + return dberr; + } +} + +void DBData::copyToBuffer( const char* pSrcData, int nSize ) +{ + m_nSize = nSize; + delete m_pBuffer; + m_pBuffer = new char[m_nSize+1]; + memcpy( m_pBuffer, pSrcData, m_nSize ); + m_pBuffer[m_nSize] = 0; +} + + +// DBHelp + +bool DBHelp::implReadLenAndData( const char* pData, int& riPos, DBData& rValue ) +{ + bool bSuccess = false; + + // Read key len + const char* pStartPtr = pData + riPos; + char* pEndPtr; + sal_Int32 nKeyLen = strtol( pStartPtr, &pEndPtr, 16 ); + if( pEndPtr == pStartPtr ) + return bSuccess; + riPos += (pEndPtr - pStartPtr) + 1; + + const char* pKeySrc = pData + riPos; + rValue.copyToBuffer( pKeySrc, nKeyLen ); + riPos += nKeyLen + 1; + + bSuccess = true; + return bSuccess; +} + +#ifdef TEST_DBHELP + +typedef std::pair< rtl::OString, rtl::OString > KeyValPair; +typedef std::vector< KeyValPair > KeyValPairVector; + +void testWriteKeyValue( FILE* pFile, const KeyValPair& rKeyValPair ) +{ + if( pFile == NULL ) + return; + char cLF = 10; + + const rtl::OString& aKeyStr = rKeyValPair.first; + const rtl::OString& aValueStr = rKeyValPair.second; + int nKeyLen = aKeyStr.getLength(); + int nValueLen = aValueStr.getLength(); + fprintf( pFile, "%x ", nKeyLen ); + if( nKeyLen > 0 ) + fwrite( aKeyStr.getStr(), 1, nKeyLen, pFile );
+ fprintf( pFile, " %x ", nValueLen ); + if( nValueLen > 0 ) + fwrite( aValueStr.getStr(), 1, nValueLen, pFile );
+ fprintf( pFile, "%c", cLF ); +} + +bool DBHelp::testAgainstDb( const rtl::OString& fileName, bool bOldDbAccess ) +{ + bool bSuccess = true; + + KeyValPairVector avKeyValPair; + + rtl::OString aOutFileName = fileName; + aOutFileName += "_TestOut"; + if( bOldDbAccess ) + aOutFileName += "_Old"; + FILE* pFile = fopen( aOutFileName.getStr(), "wb" ); + + // Get all values + Db table; + if( 0 == table.open( 0,fileName.getStr(),0,DB_BTREE,DB_RDONLY,0644 ) ) + { + bool first = true; + + Dbc* cursor = 0; + table.cursor( 0,&cursor,0 ); + Dbt key_,data; + key_.set_flags( DB_DBT_MALLOC ); // Initially the cursor must allocate the necessary memory + data.set_flags( DB_DBT_MALLOC ); + + while( cursor && DB_NOTFOUND != cursor->get( &key_,&data,DB_NEXT ) ) + { + rtl::OString keyword( static_cast<sal_Char*>(key_.get_data()), + key_.get_size() ); + rtl::OString value( static_cast<sal_Char*>(data.get_data()), + data.get_size() ); + + KeyValPair aPair( keyword, value ); + avKeyValPair.push_back( aPair ); + if( pFile != NULL ) + testWriteKeyValue( pFile, aPair ); + + if( first ) + { + key_.set_flags( DB_DBT_REALLOC ); + data.set_flags( DB_DBT_REALLOC ); + first = false; + } + } + + if( cursor ) cursor->close(); + } + table.close( 0 ); + + // TEST + DBData aDBData; + Db tableTest; + Dbt data; + + int nOkCount = 0; + int nErrCount = 0; + + bool bTestSuccess; + const char* pTestReadData = NULL; + int nTestReadDataSize = 0; + + sal_uInt32 starttime = osl_getGlobalTimer();
+ sal_uInt32 afterfirsttime = starttime;
+
+ if( pFile != NULL ) { - // static void raise_error(int dberr, const char * where); + if( bOldDbAccess ) + fprintf( pFile, "\nTesting old access:\n" ); + else + fprintf( pFile, "\nTesting new access:\n" ); + } + + KeyValPairVector::const_iterator it; + bool bFirst = true; + for( it = avKeyValPair.begin() ; it != avKeyValPair.end() ; ++it ) + { + const KeyValPair& rKeyValPair = *it; + + const rtl::OString& aKeyStr = rKeyValPair.first; + const rtl::OString& aValueStr = rKeyValPair.second; + int nKeyLen = aKeyStr.getLength(); + int nValueLen = aValueStr.getLength(); - static inline int check_error(int dberr, const char * where) + const sal_Char* ptr = aValueStr.getStr(); + + bTestSuccess = false; + pTestReadData = NULL; + nTestReadDataSize = 0; + if( bOldDbAccess ) + { + if( bFirst ) + { + if( tableTest.open( 0,fileName.getStr(),0,DB_BTREE,DB_RDONLY,0644 ) ) + { + if( pFile != NULL ) + fprintf( pFile, "Cannot open database\n" ); + + break; + } + } + + Dbt key( static_cast< void* >( const_cast< sal_Char* >( aKeyStr.getStr() ) ), aKeyStr.getLength() ); + int err = tableTest.get( 0, &key, &data, 0 ); + if( err == 0 ) + { + bTestSuccess = true; + pTestReadData = static_cast< sal_Char* >( data.get_data() ); + nTestReadDataSize = data.get_size(); + } + } + else + { + bTestSuccess = getValueForKey( aKeyStr, aDBData ); + if( bTestSuccess ) + { + pTestReadData = aDBData.getData(); + nTestReadDataSize = aDBData.getSize(); + } + } + if( bFirst ) + { + afterfirsttime = osl_getGlobalTimer();
+ bFirst = false; + } + int nError = 0; + if( bTestSuccess && pTestReadData != NULL ) { - (void)where; + int nCmp = memcmp( ptr, pTestReadData, nValueLen );
+ if( nCmp == 0 )
+ ++nOkCount;
+ else
+ nError = 1;
+
+ if( nValueLen != nTestReadDataSize ) + nError = 2;
+ } + else + nError = 3; - // if (dberr) raise_error(dberr,where); - return dberr; + if( nError != 0 ) + { + bSuccess = false; + ++nErrCount; + + if( pFile != NULL ) + { + fprintf( pFile, "ERROR, not found:\n" ); + testWriteKeyValue( pFile, rKeyValPair ); + fprintf( pFile, "\nError Code: %d\n", nError ); + }
} } + tableTest.close( 0 ); + + sal_uInt32 endtime = osl_getGlobalTimer();
+ double dDiffTime = (endtime-starttime) / 1000.0;
+ double dDiffFirstTime = (afterfirsttime-starttime) / 1000.0;
+ if( pFile != NULL ) + { + int nCount = avKeyValPair.size(); + fprintf( pFile, "%d key/values in total, read %d correctly, %d errors\n", + nCount, nOkCount, nErrCount ); + fprintf( pFile, "Time taken: %g s (First access %g s)\n", dDiffTime, dDiffFirstTime ); + fprintf( pFile, "Average time per access: %g s\n", dDiffTime / nCount ); + } + + if( pFile != NULL ) + fclose( pFile ); + + return bSuccess; +} + +#endif + + +void DBHelp::createHashMap( bool bOptimizeForPerformance ) +{ + releaseHashMap(); + if( bOptimizeForPerformance ) + { + if( m_pStringToDataMap != NULL ) + return; + m_pStringToDataMap = new StringToDataMap(); + } + else + { + if( m_pStringToValPosMap != NULL ) + return; + m_pStringToValPosMap = new StringToValPosMap(); + } + + Reference< XInputStream > xIn = m_xSFA->openFileRead( m_aFileName ); + if( xIn.is() ) + { + Sequence< sal_Int8 > aData; + sal_Int32 nSize = m_xSFA->getSize( m_aFileName ); + sal_Int32 nRead = xIn->readBytes( aData, nSize ); + + const char* pData = (const char*)aData.getConstArray(); + int iPos = 0; + while( iPos < nRead ) + { + DBData aDBKey; + if( !implReadLenAndData( pData, iPos, aDBKey ) ) + break; + + rtl::OString aOKeyStr = aDBKey.getData(); + + // Read val len + const char* pStartPtr = pData + iPos; + char* pEndPtr; + sal_Int32 nValLen = strtol( pStartPtr, &pEndPtr, 16 ); + if( pEndPtr == pStartPtr ) + break; + + iPos += (pEndPtr - pStartPtr) + 1; + + if( bOptimizeForPerformance ) + { + const char* pValSrc = pData + iPos; + rtl::OString aValStr( pValSrc, nValLen ); + (*m_pStringToDataMap)[aOKeyStr] = aValStr; + } + else + { + // store value start position + (*m_pStringToValPosMap)[aOKeyStr] = std::pair<int,int>( iPos, nValLen ); + } + iPos += nValLen + 1; + } + + xIn->closeInput(); + } +} + +void DBHelp::releaseHashMap( void ) +{ + if( m_pStringToDataMap != NULL ) + { + delete m_pStringToDataMap; + m_pStringToDataMap = NULL; + } + if( m_pStringToValPosMap != NULL ) + { + delete m_pStringToValPosMap; + m_pStringToValPosMap = NULL; + } +} + + +bool DBHelp::getValueForKey( const rtl::OString& rKey, DBData& rValue ) +{ + bool bSuccess = false; + if( !m_xSFA.is() ) + return bSuccess; + + try + { + + if( m_pStringToDataMap == NULL && m_pStringToValPosMap == NULL ) + { + bool bOptimizeForPerformance = false; + createHashMap( bOptimizeForPerformance ); + } + + if( m_pStringToValPosMap != NULL ) + { + StringToValPosMap::const_iterator it = m_pStringToValPosMap->find( rKey ); + if( it != m_pStringToValPosMap->end() ) + { + const std::pair<int,int>& rValPair = it->second; + int iValuePos = rValPair.first; + int nValueLen = rValPair.second; + + Reference< XInputStream > xIn = m_xSFA->openFileRead( m_aFileName ); + if( xIn.is() ) + { + Reference< XSeekable > xXSeekable( xIn, UNO_QUERY ); + if( xXSeekable.is() ) + { + xXSeekable->seek( iValuePos );
+
+ Sequence< sal_Int8 > aData; + sal_Int32 nRead = xIn->readBytes( aData, nValueLen ); + if( nRead == nValueLen ) + { + const char* pData = (const sal_Char*)aData.getConstArray(); + rValue.copyToBuffer( pData, nValueLen ); + bSuccess = true; + } + } + xIn->closeInput(); + } + } + } + + else if( m_pStringToDataMap != NULL ) + { + StringToDataMap::const_iterator it = m_pStringToDataMap->find( rKey ); + if( it != m_pStringToDataMap->end() ) + { + const rtl::OString& rValueStr = it->second; + int nValueLen = rValueStr.getLength(); + const char* pData = rValueStr.getStr(); + rValue.copyToBuffer( pData, nValueLen ); + bSuccess = true; + } + } + + } + catch( Exception & ) + { + bSuccess = false; + } + + return bSuccess; +} + +bool DBHelp::startIteration( void ) +{ + bool bSuccess = false; + + sal_Int32 nSize = m_xSFA->getSize( m_aFileName ); + + Reference< XInputStream > xIn = m_xSFA->openFileRead( m_aFileName ); + if( xIn.is() ) + { + m_nItRead = xIn->readBytes( m_aItData, nSize ); + if( m_nItRead == nSize ) + { + bSuccess = true; + m_pItData = (const char*)m_aItData.getConstArray(); + m_iItPos = 0; + } + else + { + stopIteration(); + } + } + + return bSuccess; +} + +bool DBHelp::getNextKeyAndValue( DBData& rKey, DBData& rValue ) +{ + bool bSuccess = false; + + if( m_iItPos < m_nItRead ) + { + if( implReadLenAndData( m_pItData, m_iItPos, rKey ) ) + { + if( implReadLenAndData( m_pItData, m_iItPos, rValue ) ) + bSuccess = true; + } + } + + return bSuccess; +} + +void DBHelp::stopIteration( void ) +{ + m_aItData = Sequence<sal_Int8>(); + m_pItData = NULL; + m_nItRead = -1; + m_iItPos = -1; +} + Db::Db() { db_internal::check_error( db_create(&m_pDBP,0,0),"Db::Db" ); + m_pDBHelp = NULL; } @@ -66,6 +500,7 @@ Db::~Db() // TODO: add assert } + delete m_pDBHelp; } @@ -159,6 +594,7 @@ Dbt::Dbt(void *data_arg, u_int32_t size_arg) this->set_size(size_arg); } +/* Dbt::Dbt(const Dbt & other) { using namespace std; @@ -178,6 +614,7 @@ Dbt& Dbt::operator = (const Dbt & other) } return *this; } +*/ Dbt::~Dbt() { |