summaryrefslogtreecommitdiff
path: root/xmlhelp/source/cxxhelp/provider/db.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'xmlhelp/source/cxxhelp/provider/db.cxx')
-rw-r--r--xmlhelp/source/cxxhelp/provider/db.cxx453
1 files changed, 445 insertions, 8 deletions
diff --git a/xmlhelp/source/cxxhelp/provider/db.cxx b/xmlhelp/source/cxxhelp/provider/db.cxx
index c98f51eab3..a8d8769882 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 ) )
{
- // static void raise_error(int dberr, const char * where);
+ bool first = true;
- static inline int check_error(int dberr, const char * where)
+ 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 ) )
{
- (void)where;
-
- // if (dberr) raise_error(dberr,where);
- return dberr;
+ 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 )
+ {
+ 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();
+
+ 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 )
+ {
+ int nCmp = memcmp( ptr, pTestReadData, nValueLen );
+ if( nCmp == 0 )
+ ++nOkCount;
+ else
+ nError = 1;
+
+ if( nValueLen != nTestReadDataSize )
+ nError = 2;
+ }
+ else
+ nError = 3;
+
+ 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;
}
@@ -65,7 +499,8 @@ Db::~Db()
// should not happen
// 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()
{