Kaydet (Commit) 2ecaf778 authored tarafından Kohei Yoshida's avatar Kohei Yoshida

Use mdds::flat_segment_tree to store row flags.

Much less memory footprint & better scalability.

Change-Id: Idef9afe5fa6e247e59fb949d4c9955fab4f669dc
üst 2a2e5986
...@@ -38,7 +38,8 @@ ...@@ -38,7 +38,8 @@
#include <boost/unordered_set.hpp> #include <boost/unordered_set.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
class Date; #include <mdds/flat_segment_tree.hpp>
class ScDPItemData; class ScDPItemData;
class ScDPCache; class ScDPCache;
class ScDocument; class ScDocument;
...@@ -132,7 +133,7 @@ public: ...@@ -132,7 +133,7 @@ public:
/** Check whether a specified row is active or not. When a row is active, /** Check whether a specified row is active or not. When a row is active,
it is used in calculation of the results data. A row becomes inactive it is used in calculation of the results data. A row becomes inactive
when it is filtered out by page field. */ when it is filtered out by page field. */
bool isRowActive(sal_Int32 nRow) const; bool isRowActive(sal_Int32 nRow, sal_Int32* pLastRow = NULL) const;
/** Set filter on/off flag to each row to control visibility. The caller /** Set filter on/off flag to each row to control visibility. The caller
must ensure that the table is filled before calling this function. */ must ensure that the table is filled before calling this function. */
...@@ -175,11 +176,15 @@ private: ...@@ -175,11 +176,15 @@ private:
bool isRowQualified(sal_Int32 nRow, const ::std::vector<Criterion>& rCriteria, const ::boost::unordered_set<sal_Int32>& rRepeatIfEmptyDims) const; bool isRowQualified(sal_Int32 nRow, const ::std::vector<Criterion>& rCriteria, const ::boost::unordered_set<sal_Int32>& rRepeatIfEmptyDims) const;
private: private:
typedef mdds::flat_segment_tree<SCROW, bool> RowFlagType;
/** unique field entires for each field (column). */ /** unique field entires for each field (column). */
::std::vector< ::std::vector<SCROW> > maFieldEntries; ::std::vector< ::std::vector<SCROW> > maFieldEntries;
/** Row flags. The first row below the header row has the index of 0. */ /** Rows visible by standard filter query. */
::std::vector<RowFlag> maRowFlags; RowFlagType maShowByFilter;
/** Rows visible by page dimension filtering. */
RowFlagType maShowByPage;
const ScDPCache* mpCache; const ScDPCache* mpCache;
}; };
......
...@@ -125,7 +125,7 @@ ScDPCacheTable::Criterion::Criterion() : ...@@ -125,7 +125,7 @@ ScDPCacheTable::Criterion::Criterion() :
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
ScDPCacheTable::ScDPCacheTable(const ScDPCache* pCache) : ScDPCacheTable::ScDPCacheTable(const ScDPCache* pCache) :
mpCache(pCache) maShowByFilter(0, MAXROW+1, false), maShowByPage(0, MAXROW+1, true), mpCache(pCache)
{ {
} }
...@@ -152,29 +152,26 @@ void ScDPCacheTable::fillTable( ...@@ -152,29 +152,26 @@ void ScDPCacheTable::fillTable(
if (nRowCount <= 0 || nColCount <= 0) if (nRowCount <= 0 || nColCount <= 0)
return; return;
maRowFlags.clear(); maShowByFilter.clear();
maRowFlags.reserve(nRowCount); maShowByPage.clear();
// Process the non-empty data rows. // Process the non-empty data rows.
for (SCROW nRow = 0; nRow < nDataSize; ++nRow) for (SCROW nRow = 0; nRow < nDataSize; ++nRow)
{ {
maRowFlags.push_back(RowFlag());
if (!getCache()->ValidQuery(nRow, rQuery)) if (!getCache()->ValidQuery(nRow, rQuery))
continue; continue;
if (bIgnoreEmptyRows && getCache()->IsRowEmpty(nRow)) if (bIgnoreEmptyRows && getCache()->IsRowEmpty(nRow))
continue; continue;
maRowFlags.back().mbShowByFilter = true; maShowByFilter.insert_back(nRow, nRow+1, true);
} }
// Process the trailing empty rows. // Process the trailing empty rows.
for (SCROW nRow = nDataSize; nRow < nRowCount; ++nRow) if (!bIgnoreEmptyRows)
{ maShowByFilter.insert_back(nDataSize, nRowCount, true);
maRowFlags.push_back(RowFlag());
if (!bIgnoreEmptyRows) maShowByFilter.build_tree();
maRowFlags.back().mbShowByFilter = true;
}
// Initialize field entries container. // Initialize field entries container.
maFieldEntries.clear(); maFieldEntries.clear();
...@@ -189,11 +186,25 @@ void ScDPCacheTable::fillTable( ...@@ -189,11 +186,25 @@ void ScDPCacheTable::fillTable(
continue; continue;
std::vector<SCROW> aAdded(nMemCount, -1); std::vector<SCROW> aAdded(nMemCount, -1);
bool bShow = false;
SCROW nEndSegment = -1;
for (SCROW nRow = 0; nRow < nRowCount; ++nRow) for (SCROW nRow = 0; nRow < nRowCount; ++nRow)
{ {
if (!maRowFlags[nRow].mbShowByFilter) if (nRow > nEndSegment)
{
if (!maShowByFilter.search_tree(nRow, bShow, NULL, &nEndSegment))
{
OSL_FAIL("Tree search failed!");
continue;
}
--nEndSegment; // End position is not inclusive. Move back one.
}
if (!bShow)
{
nRow = nEndSegment;
continue; continue;
}
SCROW nIndex = getCache()->GetItemDataId(nCol, nRow, bRepeatIfEmpty); SCROW nIndex = getCache()->GetItemDataId(nCol, nRow, bRepeatIfEmpty);
SCROW nOrder = getOrder(nCol, nIndex); SCROW nOrder = getOrder(nCol, nIndex);
...@@ -214,63 +225,66 @@ void ScDPCacheTable::fillTable() ...@@ -214,63 +225,66 @@ void ScDPCacheTable::fillTable()
if (nRowCount <= 0 || nColCount <= 0) if (nRowCount <= 0 || nColCount <= 0)
return; return;
maRowFlags.clear(); maShowByFilter.clear();
maRowFlags.reserve(nRowCount); maShowByPage.clear();
maShowByFilter.insert_front(0, nRowCount, true);
for (SCROW nRow = 0; nRow < nRowCount; ++nRow)
{ // Initialize field entries container.
maRowFlags.push_back(RowFlag()); maFieldEntries.clear();
maRowFlags.back().mbShowByFilter = true; maFieldEntries.reserve(nColCount);
}
// Data rows
// Initialize field entries container. for (SCCOL nCol = 0; nCol < nColCount; ++nCol)
maFieldEntries.clear(); {
maFieldEntries.reserve(nColCount); maFieldEntries.push_back( vector<SCROW>() );
SCROW nMemCount = getCache()->GetDimMemberCount( nCol );
// Data rows if (!nMemCount)
for (SCCOL nCol = 0; nCol < nColCount; ++nCol) continue;
{
maFieldEntries.push_back( vector<SCROW>() ); std::vector<SCROW> aAdded(nMemCount, -1);
SCROW nMemCount = getCache()->GetDimMemberCount( nCol );
if (!nMemCount) for (SCROW nRow = 0; nRow < nRowCount; ++nRow)
continue; {
SCROW nIndex = getCache()->GetItemDataId(nCol, nRow, false);
std::vector<SCROW> aAdded(nMemCount, -1); SCROW nOrder = getOrder(nCol, nIndex);
aAdded[nOrder] = nIndex;
for (SCROW nRow = 0; nRow < nRowCount; ++nRow) }
{ for (SCROW nRow = 0; nRow < nMemCount; ++nRow)
SCROW nIndex = getCache()->GetItemDataId(nCol, nRow, false); {
SCROW nOrder = getOrder(nCol, nIndex); if (aAdded[nRow] != -1)
aAdded[nOrder] = nIndex; maFieldEntries.back().push_back(aAdded[nRow]);
} }
for (SCROW nRow = 0; nRow < nMemCount; ++nRow) }
{
if (aAdded[nRow] != -1)
maFieldEntries.back().push_back(aAdded[nRow]);
}
}
} }
bool ScDPCacheTable::isRowActive(sal_Int32 nRow) const bool ScDPCacheTable::isRowActive(sal_Int32 nRow, sal_Int32* pLastRow) const
{ {
if (nRow < 0 || static_cast<size_t>(nRow) >= maRowFlags.size()) bool bFilter = false, bPage = true;
// row index out of bound SCROW nLastRowFilter = MAXROW, nLastRowPage = MAXROW;
return false; maShowByFilter.search_tree(nRow, bFilter, NULL, &nLastRowFilter);
maShowByPage.search_tree(nRow, bPage, NULL, &nLastRowPage);
if (pLastRow)
{
// Return the last row of current segment.
*pLastRow = nLastRowFilter < nLastRowPage ? nLastRowFilter : nLastRowPage;
*pLastRow -= 1; // End position is not inclusive. Move back one.
}
return maRowFlags[nRow].isActive(); return bFilter && bPage;
} }
void ScDPCacheTable::filterByPageDimension(const vector<Criterion>& rCriteria, const boost::unordered_set<sal_Int32>& rRepeatIfEmptyDims) void ScDPCacheTable::filterByPageDimension(const vector<Criterion>& rCriteria, const boost::unordered_set<sal_Int32>& rRepeatIfEmptyDims)
{ {
sal_Int32 nRowSize = getRowSize(); SCROW nRowSize = getRowSize();
if (nRowSize != static_cast<sal_Int32>(maRowFlags.size()))
maShowByPage.clear();
for (SCROW nRow = 0; nRow < nRowSize; ++nRow)
{ {
// sizes of the two tables differ! bool bShow = isRowQualified(nRow, rCriteria, rRepeatIfEmptyDims);
return; maShowByPage.insert_back(nRow, nRow+1, bShow);
} }
for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow) maShowByPage.build_tree();
maRowFlags[nRow].mbShowByPage = isRowQualified(nRow, rCriteria, rRepeatIfEmptyDims);
} }
const ScDPItemData* ScDPCacheTable::getCell(SCCOL nCol, SCROW nRow, bool bRepeatIfEmpty) const const ScDPItemData* ScDPCacheTable::getCell(SCCOL nCol, SCROW nRow, bool bRepeatIfEmpty) const
...@@ -340,12 +354,15 @@ void ScDPCacheTable::filterTable(const vector<Criterion>& rCriteria, Sequence< S ...@@ -340,12 +354,15 @@ void ScDPCacheTable::filterTable(const vector<Criterion>& rCriteria, Sequence< S
} }
tableData.push_back(headerRow); tableData.push_back(headerRow);
for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow) for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow)
{ {
if (!maRowFlags[nRow].isActive()) sal_Int32 nLastRow;
if (!isRowActive(nRow, &nLastRow))
{
// This row is filtered out. // This row is filtered out.
nRow = nLastRow;
continue; continue;
}
if (!isRowQualified(nRow, rCriteria, rRepeatIfEmptyDims)) if (!isRowQualified(nRow, rCriteria, rRepeatIfEmptyDims))
continue; continue;
...@@ -385,7 +402,8 @@ SCROW ScDPCacheTable::getOrder(long nDim, SCROW nIndex) const ...@@ -385,7 +402,8 @@ SCROW ScDPCacheTable::getOrder(long nDim, SCROW nIndex) const
void ScDPCacheTable::clear() void ScDPCacheTable::clear()
{ {
maFieldEntries.clear(); maFieldEntries.clear();
maRowFlags.clear(); maShowByFilter.clear();
maShowByPage.clear();
} }
bool ScDPCacheTable::empty() const bool ScDPCacheTable::empty() const
......
...@@ -762,8 +762,12 @@ void ScDPGroupTableData::CalcResults(CalcInfo& rInfo, bool bAutoShow) ...@@ -762,8 +762,12 @@ void ScDPGroupTableData::CalcResults(CalcInfo& rInfo, bool bAutoShow)
sal_Int32 nRowSize = rCacheTable.getRowSize(); sal_Int32 nRowSize = rCacheTable.getRowSize();
for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow) for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow)
{ {
if (!rCacheTable.isRowActive(nRow)) sal_Int32 nLastRow;
if (!rCacheTable.isRowActive(nRow, &nLastRow))
{
nRow = nLastRow;
continue; continue;
}
CalcRowData aData; CalcRowData aData;
FillRowDataFromCacheTable(nRow, rCacheTable, rInfo, aData); FillRowDataFromCacheTable(nRow, rCacheTable, rInfo, aData);
......
...@@ -221,8 +221,12 @@ void ScDPTableData::CalcResultsFromCacheTable(const ScDPCacheTable& rCacheTable, ...@@ -221,8 +221,12 @@ void ScDPTableData::CalcResultsFromCacheTable(const ScDPCacheTable& rCacheTable,
sal_Int32 nRowSize = rCacheTable.getRowSize(); sal_Int32 nRowSize = rCacheTable.getRowSize();
for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow) for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow)
{ {
if (!rCacheTable.isRowActive(nRow)) sal_Int32 nLastRow;
if (!rCacheTable.isRowActive(nRow, &nLastRow))
{
nRow = nLastRow;
continue; continue;
}
CalcRowData aData; CalcRowData aData;
FillRowDataFromCacheTable(nRow, rCacheTable, rInfo, aData); FillRowDataFromCacheTable(nRow, rCacheTable, rInfo, aData);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment