Guard cache access with mutex & a new method just to check for range name.

Change-Id: Id24b5ba72362f9d878b4878c1e807bed3e596b20
diff --git a/sc/inc/externalrefmgr.hxx b/sc/inc/externalrefmgr.hxx
index 6156abb..b3d35f9 100644
--- a/sc/inc/externalrefmgr.hxx
+++ b/sc/inc/externalrefmgr.hxx
@@ -233,6 +233,7 @@ public:

    ScExternalRefCache::TokenArrayRef getRangeNameTokens(sal_uInt16 nFileId, const OUString& rName);
    void setRangeNameTokens(sal_uInt16 nFileId, const OUString& rName, TokenArrayRef pArray);
    bool isValidRangeName(sal_uInt16 nFileId, const OUString& rName) const;

    void setCellData(sal_uInt16 nFileId, const OUString& rTabName,
                     SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uLong nFmtIndex);
@@ -557,6 +558,8 @@ public:
    ScExternalRefCache::TokenArrayRef getRangeNameTokens(
        sal_uInt16 nFileId, const OUString& rName, const ScAddress* pCurPos = NULL);

    bool isValidRangeName(sal_uInt16 nFileId, const OUString& rName);

    OUString getOwnDocumentName() const;
    bool isOwnDocument(const OUString& rFile) const;

@@ -765,6 +768,12 @@ private:
private:
    ScDocument* mpDoc;

    /** Mutex for accessing cached data and/or source document shells. */
    mutable osl::Mutex maMtxCacheAccess;

    /** Mutex for source document meta-data access. */
    mutable osl::Mutex maMtxSrcFiles;

    /** cache of referenced ranges and names from source documents. */
    ScExternalRefCache maRefCache;

@@ -798,7 +807,6 @@ private:
     * external document identifiers.
     */
    std::vector<SrcFileData> maSrcFiles;
    mutable osl::Mutex maMtxSrcFiles;

    /** Status whether in reference marking state. See isInReferenceMarking(). */
    bool mbInReferenceMarking:1;
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index 62bf259..6b6d011 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -2914,7 +2914,7 @@ bool ScCompiler::IsExternalNamedRange( const OUString& rSymbol )
    pRefMgr->convertToAbsName(aTmp);
    aFile = aTmp;
    sal_uInt16 nFileId = pRefMgr->getExternalFileId(aFile);
    if (!pRefMgr->getRangeNameTokens(nFileId, aName).get())
    if (!pRefMgr->isValidRangeName(nFileId, aName))
        // range name doesn't exist in the source document.
        return false;

diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
index 1561cbb..9c07fd7 100644
--- a/sc/source/ui/docshell/externalrefmgr.cxx
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -710,6 +710,18 @@ void ScExternalRefCache::setRangeNameTokens(sal_uInt16 nFileId, const OUString& 
    pDoc->maRealRangeNameMap.insert(NamePairMap::value_type(aUpperName, rName));
}

bool ScExternalRefCache::isValidRangeName(sal_uInt16 nFileId, const OUString& rName) const
{
    osl::MutexGuard aGuard(&maMtxDocs);

    DocItem* pDoc = getDocItem(nFileId);
    if (!pDoc)
        return false;

    const RangeNameMap& rMap = pDoc->maRangeNames;
    return rMap.count(rName) > 0;
}

void ScExternalRefCache::setCellData(sal_uInt16 nFileId, const OUString& rTabName, SCCOL nCol, SCROW nRow,
                                     TokenRef pToken, sal_uLong nFmtIndex)
{
@@ -1747,6 +1759,8 @@ ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken(
    sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rCell,
    const ScAddress* pCurPos, SCTAB* pTab, ScExternalRefCache::CellFormat* pFmt)
{
    osl::MutexGuard aGuard(&maMtxCacheAccess);

    if (pCurPos)
        insertRefCell(nFileId, *pCurPos);

@@ -1839,6 +1853,8 @@ ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken(
ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokens(
    sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange, const ScAddress* pCurPos)
{
    osl::MutexGuard aGuard(&maMtxCacheAccess);

    if (pCurPos)
        insertRefCell(nFileId, *pCurPos);

@@ -1885,6 +1901,8 @@ ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokens(
ScExternalRefCache::TokenArrayRef ScExternalRefManager::getRangeNameTokens(
    sal_uInt16 nFileId, const OUString& rName, const ScAddress* pCurPos)
{
    osl::MutexGuard aGuard(&maMtxCacheAccess);

    if (pCurPos)
        insertRefCell(nFileId, *pCurPos);

@@ -1924,6 +1942,42 @@ ScExternalRefCache::TokenArrayRef ScExternalRefManager::getRangeNameTokens(
    return pArray;
}

namespace {

bool hasRangeName(ScDocument& rDoc, const OUString& rName)
{
    ScRangeName* pExtNames = rDoc.GetRangeName();
    OUString aUpperName = ScGlobal::pCharClass->uppercase(rName);
    const ScRangeData* pRangeData = pExtNames->findByUpperName(aUpperName);
    return pRangeData != NULL;
}

}

bool ScExternalRefManager::isValidRangeName(sal_uInt16 nFileId, const OUString& rName)
{
    osl::MutexGuard aGuard(&maMtxCacheAccess);

    maybeLinkExternalFile(nFileId);
    ScDocument* pSrcDoc = getInMemorySrcDocument(nFileId);
    if (pSrcDoc)
    {
        // Only check the presence of the name.
        return hasRangeName(*pSrcDoc, rName);
    }

    if (maRefCache.isValidRangeName(nFileId, rName))
        // Range name is cached.
        return true;

    pSrcDoc = getSrcDocument(nFileId);
    if (!pSrcDoc)
        // failed to load document from disk.
        return false;

    return hasRangeName(*pSrcDoc, rName);
}

void ScExternalRefManager::refreshAllRefCells(sal_uInt16 nFileId)
{
    RefCellMap::iterator itrFile = maRefCells.find(nFileId);