Index: src/libchcore/TSQLiteSerializerContainer.cpp =================================================================== diff -u -N -ra3d1e4c03280ece94af75d9aef32a65266cf8050 -rffdee64cb0f2d472bb4102abe80ee12783e794c8 --- src/libchcore/TSQLiteSerializerContainer.cpp (.../TSQLiteSerializerContainer.cpp) (revision a3d1e4c03280ece94af75d9aef32a65266cf8050) +++ src/libchcore/TSQLiteSerializerContainer.cpp (.../TSQLiteSerializerContainer.cpp) (revision ffdee64cb0f2d472bb4102abe80ee12783e794c8) @@ -26,33 +26,40 @@ #include "TSQLiteSerializerRowReader.h" #include "TRemovedObjects.h" #include "SerializerTrace.h" +#include +#include "TSerializerException.h" BEGIN_CHCORE_NAMESPACE using namespace sqlite; TSQLiteSerializerContainer::TSQLiteSerializerContainer(const TString& strName, const sqlite::TSQLiteDatabasePtr& spDB) : m_strName(strName), - m_spDB(spDB) + m_spDB(spDB), + m_pPoolRows(NULL) { } -TSQLiteSerializerContainer::TSQLiteSerializerContainer(const TString& strName, size_t stParentID, const sqlite::TSQLiteDatabasePtr& spDB) : - m_stParentID(stParentID), - m_strName(strName), - m_spDB(spDB) -{ -} - TSQLiteSerializerContainer::~TSQLiteSerializerContainer() { + // get rid of all rows first + m_mapRows.clear(); + + // now get rid of memory pool + delete m_pPoolRows; } ISerializerRowData& TSQLiteSerializerContainer::GetRow(size_t stRowID, bool bMarkAsAdded) { RowMap::iterator iterFnd = m_mapRows.find(stRowID); if(iterFnd == m_mapRows.end()) - iterFnd = m_mapRows.insert(std::make_pair(stRowID, TSQLiteSerializerRowData(stRowID, m_tColumns, bMarkAsAdded))).first; + { + void* pMemoryBlock = GetPool().malloc(); + if(!pMemoryBlock) + THROW_SERIALIZER_EXCEPTION(eErr_InternalProblem, _T("Cannot allocate memory")); + + iterFnd = m_mapRows.insert(std::make_pair(stRowID, TSQLiteSerializerRowData(stRowID, m_tColumns, bMarkAsAdded, (unsigned long long*)pMemoryBlock, GetPool().get_requested_size()))).first; + } else if(bMarkAsAdded) iterFnd->second.MarkAsAdded(); @@ -93,12 +100,12 @@ FlushDeletions(); // group rows that can be executed with one preparation - std::map> mapGroups; - std::map>::iterator iterMapGroups; + std::map> mapGroups; + std::map>::iterator iterMapGroups; for(RowMap::iterator iterRows = m_mapRows.begin(); iterRows != m_mapRows.end(); ++iterRows) { - TRowID rowID = iterRows->second.GetChangeIdentification(); + unsigned long long rowID = iterRows->second.GetChangeIdentification(); iterMapGroups = mapGroups.find(rowID); if(iterMapGroups == mapGroups.end()) iterMapGroups = mapGroups.insert(std::make_pair(rowID, std::vector())).first; @@ -110,24 +117,26 @@ for(iterMapGroups = mapGroups.begin(); iterMapGroups != mapGroups.end(); ++iterMapGroups) { - if(iterMapGroups->first.HasAny()) + if(iterMapGroups->first != 0) { std::vector& rGroupRows = iterMapGroups->second; // query is generated from the first item in a group TString strQuery = rGroupRows.front()->GetQuery(m_strName); + if(!strQuery.IsEmpty()) + { + DBTRACE2(_T("Preparing query for %lu records: %s\n"), (unsigned long)iterMapGroups->second.size(), (PCTSTR)strQuery); - DBTRACE2(_T("Preparing query for %lu records: %s\n"), (unsigned long)iterMapGroups->second.size(), (PCTSTR)strQuery); + tStatement.Prepare(strQuery); - tStatement.Prepare(strQuery); + for(std::vector::iterator iterRow = iterMapGroups->second.begin(); iterRow != iterMapGroups->second.end(); ++iterRow) + { + (*iterRow)->BindParamsAndExec(tStatement); + tStatement.ClearBindings(); + } - for(std::vector::iterator iterRow = iterMapGroups->second.begin(); iterRow != iterMapGroups->second.end(); ++iterRow) - { - (*iterRow)->BindParamsAndExec(tStatement); - tStatement.ClearBindings(); + tStatement.Close(); } - - tStatement.Close(); } } } @@ -160,4 +169,28 @@ } } +boost::pool<>& TSQLiteSerializerContainer::GetPool() +{ + if(!m_pPoolRows) + m_pPoolRows = new boost::pool<>(CalculateRowMemorySize()); + else + { + if(m_pPoolRows->get_requested_size() != CalculateRowMemorySize()) + THROW_SERIALIZER_EXCEPTION(eErr_InternalProblem, _T("Column count changed after first use")); + } + + return *m_pPoolRows; +} + +size_t TSQLiteSerializerContainer::CalculateRowMemorySize() const +{ + // assume 64bit column mask (8 bytes) + const size_t stMaskSize = 8; + + // and additionally 64bit for each column (either for storing numbers directly or for allocating string/double) + const size_t stFieldSize = 8; + + return stMaskSize + m_tColumns.GetCount() * stFieldSize; +} + END_CHCORE_NAMESPACE