diff options
Diffstat (limited to 'sw/source/core/bastyp/swcache.cxx')
-rw-r--r-- | sw/source/core/bastyp/swcache.cxx | 699 |
1 files changed, 699 insertions, 0 deletions
diff --git a/sw/source/core/bastyp/swcache.cxx b/sw/source/core/bastyp/swcache.cxx new file mode 100644 index 000000000000..54cc0fea4bae --- /dev/null +++ b/sw/source/core/bastyp/swcache.cxx @@ -0,0 +1,699 @@ +/************************************************************************* + * + * $RCSfile: swcache.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-19 00:08:16 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifdef PRECOMPILED +#include "core_pch.hxx" +#endif + +#pragma hdrstop + +#ifndef _TOOLS_DEBUG_HXX //autogen +#include <tools/debug.hxx> +#endif +#ifndef _STREAM_HXX //autogen +#include <tools/stream.hxx> +#endif +#ifndef _TOOLS_TEMPFILE_HXX +#include <tools/tempfile.hxx> +#endif +#include "errhdl.hxx" +#include "swcache.hxx" + +#ifndef PRODUCT + #include <stdlib.h> // getenv() + #include <stdio.h> // sprintf() +#endif + + +SV_IMPL_PTRARR(SwCacheObjArr,SwCacheObj*); + +#ifdef PRODUCT +#define INCREMENT( nVar ) +#else +#define INCREMENT( nVar ) ++nVar +#endif + +/************************************************************************* +|* +|* SwCache::Check() +|* +|* Ersterstellung MA 23. Mar. 94 +|* Letzte Aenderung MA 23. Mar. 94 +|* +|*************************************************************************/ + +#ifndef PRODUCT + +void SwCache::Check() +{ + if ( !pRealFirst ) + return; + + //Konsistenspruefung. + ASSERT( !pLast->GetNext(), "Last but not last." ); + ASSERT( !pRealFirst->GetPrev(), "First but not first." ); + USHORT nCnt = 0; + BOOL bFirstFound = FALSE; + SwCacheObj *pObj = pRealFirst; + SwCacheObj *pRekursive = pObj; + while ( pObj ) + { + //Das Objekt muss auch auf dem Rueckwaertsweg gefunden werden. + SwCacheObj *pTmp = pLast; + while ( pTmp && pTmp != pObj ) + pTmp = pTmp->GetPrev(); + ASSERT( pTmp, "Objekt not found." ); + + ++nCnt; + if ( pObj == pFirst ) + bFirstFound = TRUE; + if ( !pObj->GetNext() ) + ASSERT( pObj == pLast, "Last not Found." ); + pObj = pObj->GetNext(); + ASSERT( pObj != pRekursive, "Recursion in SwCache." ); + } + ASSERT( bFirstFound, "First not Found." ); + ASSERT( (nCnt + aFreePositions.Count()) == Count(), "Lost Chain." ); + if ( Count() == nCurMax ) + ASSERT( (nCurMax - nCnt) == aFreePositions.Count(), "Lost FreePositions." ); +} +#endif + +#if !defined(PRODUCT) && defined(MADEBUG) +#define CHECK Check(); +#else +#define CHECK +#endif + +/************************************************************************* +|* +|* SwCache::SwCache(), ~SwCache() +|* +|* Ersterstellung MA 15. Mar. 94 +|* Letzte Aenderung MA 15. Mar. 94 +|* +|*************************************************************************/ + + +SwCache::SwCache( const USHORT nInitSize, const USHORT nGrowSize +#ifndef PRODUCT + , const ByteString &rNm +#endif + ) : + SwCacheObjArr( (BYTE)nInitSize, (BYTE)nGrowSize ), + aFreePositions( 5, 5 ), + nMax( nInitSize ), + nCurMax( nInitSize ), + pRealFirst( 0 ), + pFirst( 0 ), + pLast( 0 ) +#ifndef PRODUCT + , aName( rNm ), + nAppend( 0 ), + nInsertFree( 0 ), + nReplace( 0 ), + nGetSuccess( 0 ), + nGetFail( 0 ), + nToTop( 0 ), + nDelete( 0 ), + nGetSeek( 0 ), + nAverageSeekCnt( 0 ), + nFlushCnt( 0 ), + nFlushedObjects( 0 ), + nIncreaseMax( 0 ), + nDecreaseMax( 0 ) +#endif +{ +} + +#ifndef PRODUCT + + + +SwCache::~SwCache() +{ +#ifndef MAC + static USHORT nOpenMode = STREAM_WRITE | STREAM_TRUNC; + String sExt(String::CreateFromAscii("log")); + TempFile aTempFile(String::CreateFromAscii("swcache"), &sExt); + SvFileStream aStream( aTempFile.GetName(), nOpenMode ); + nOpenMode = STREAM_WRITE; + + if( !aStream.GetError() ) + { + aStream.Seek( STREAM_SEEK_TO_END ); + ByteString sOut( aName ); sOut += '\n'; + (( sOut += "Anzahl neuer Eintraege: " ) += nAppend )+= '\n'; + (( sOut += "Anzahl Insert auf freie Plaetze: " ) += nInsertFree )+= '\n'; + (( sOut += "Anzahl Ersetzungen: " ) += nReplace )+= '\n'; + (( sOut += "Anzahl Erfolgreicher Get's: " ) += nGetSuccess )+= '\n'; + (( sOut += "Anzahl Fehlgeschlagener Get's: " ) += nGetFail )+= '\n'; + (( sOut += "Anzahl Umsortierungen (LRU): " ) += nToTop )+= '\n'; + (( sOut += "Anzahl Loeschungen: " ) += nDelete )+= '\n'; + (( sOut += "Anzahl Get's ohne Index: " ) += nGetSeek )+= '\n'; + (( sOut += "Anzahl Seek fuer Get ohne Index: " ) += nAverageSeekCnt )+= '\n'; + (( sOut += "Anzahl Flush-Aufrufe: " ) += nFlushCnt )+= '\n'; + (( sOut += "Anzahl geflush'ter Objekte: " ) += nFlushedObjects )+= '\n'; + (( sOut += "Anzahl Cache-Erweiterungen: " ) += nIncreaseMax )+= '\n'; + (( sOut += "Anzahl Cache-Verkleinerungen: " ) += nDecreaseMax )+= '\n'; + + aStream << sOut.GetBuffer() + << "-------------------------------------------------------" + << endl; + } + Check(); +#endif +} +#endif + +/************************************************************************* +|* +|* SwCache::Flush() +|* +|* Ersterstellung MA 15. Mar. 94 +|* Letzte Aenderung MA 15. Mar. 94 +|* +|*************************************************************************/ + + +void SwCache::Flush( const BYTE nPercent ) +{ + ASSERT( nPercent == 100, "SwCache::Flush() arbeitet nur 100%'ig" ); + + INCREMENT( nFlushCnt ); + SwCacheObj *pObj = pRealFirst; + pRealFirst = pFirst = pLast = 0; + SwCacheObj *pTmp; + while ( pObj ) + { +#ifndef PRODUCT + if ( pObj->IsLocked() ) + { + ASSERT( TRUE, "Flushing locked objects." ); + if ( !pRealFirst ) + { + pRealFirst = pFirst = pLast = pObj; + pTmp = pObj->GetNext(); + pObj->SetNext( 0 ); pObj->SetPrev( 0 ); + pObj = pTmp; + } + else + { pLast->SetNext( pObj ); + pObj->SetPrev( pLast ); + pLast = pObj; + pTmp = pObj->GetNext(); + pObj->SetNext( 0 ); + pObj = pTmp; + } + } + else +#endif + { + pTmp = (SwCacheObj*)pObj; + pObj = pTmp->GetNext(); + aFreePositions.Insert( pTmp->GetCachePos(), aFreePositions.Count() ); + *(pData + pTmp->GetCachePos()) = (void*)0; + delete pTmp; + INCREMENT( nFlushedObjects ); + } + } +} + +/************************************************************************* +|* +|* SwCache::ToTop() +|* +|* Ersterstellung MA 15. Mar. 94 +|* Letzte Aenderung MA 24. Apr. 95 +|* +|*************************************************************************/ + + +void SwCache::ToTop( SwCacheObj *pObj ) +{ + INCREMENT( nToTop ); + + //Objekt aus der LRU-Kette ausschneiden und am Anfang einfuegen. + if ( pRealFirst == pObj ) //pFirst wurde vom Aufrufer geprueft! + { CHECK; + return; + } + + if ( !pRealFirst ) + { //Der erste wird eingetragen. + ASSERT( !pFirst && !pLast, "First not first." ); + pRealFirst = pFirst = pLast = pObj; + CHECK; + return; + } + + //Ausschneiden. + if ( pObj == pLast ) + { + ASSERT( pObj->GetPrev(), "Last but no Prev." ); + pLast = pObj->GetPrev(); + pLast->SetNext( 0 ); + } + else + { + if ( pObj->GetNext() ) + pObj->GetNext()->SetPrev( pObj->GetPrev() ); + if ( pObj->GetPrev() ) + pObj->GetPrev()->SetNext( pObj->GetNext() ); + } + + //Am (virtuellen) Anfang einfuegen. + if ( pRealFirst == pFirst ) + { + pRealFirst->SetPrev( pObj ); + pObj->SetNext( pRealFirst ); + pObj->SetPrev( 0 ); + pRealFirst = pFirst = pObj; + CHECK; + } + else + { + ASSERT( pFirst, "ToTop, First ist not RealFirst an Empty." ); + + if ( pFirst->GetPrev() ) + { + pFirst->GetPrev()->SetNext( pObj ); + pObj->SetPrev( pFirst->GetPrev() ); + } + else + pObj->SetPrev( 0 ); + pFirst->SetPrev( pObj ); + pObj->SetNext( pFirst ); + pFirst = pObj; + CHECK; + } +} + +/************************************************************************* +|* +|* SwCache::Get() +|* +|* Ersterstellung MA 15. Mar. 94 +|* Letzte Aenderung MA 22. Aug. 94 +|* +|*************************************************************************/ + + +SwCacheObj *SwCache::Get( const void *pOwner, const USHORT nIndex, + const BOOL bToTop ) +{ + SwCacheObj *pRet; + if ( 0 != (pRet = nIndex < Count() ? operator[]( nIndex ) : 0) ) + { + if ( !pRet->IsOwner( pOwner ) ) + pRet = 0; + else if ( bToTop && pRet != pFirst ) + ToTop( pRet ); + } + +#ifndef PRODUCT + if ( pRet ) + ++nGetSuccess; + else + ++nGetFail; +#endif + + return pRet; +} + + + +SwCacheObj *SwCache::Get( const void *pOwner, const BOOL bToTop ) +{ + SwCacheObj *pRet = pRealFirst; + while ( pRet && !pRet->IsOwner( pOwner ) ) + { + INCREMENT( nAverageSeekCnt ); + pRet = pRet->GetNext(); + } + + if ( bToTop && pRet && pRet != pFirst ) + ToTop( pRet ); + +#ifndef PRODUCT + if ( pRet ) + ++nGetSuccess; + else + ++nGetFail; + ++nGetSeek; +#endif + return pRet; +} + +/************************************************************************* +|* +|* SwCache::Delete() +|* +|* Ersterstellung MA 15. Mar. 94 +|* Letzte Aenderung MA 15. Mar. 94 +|* +|*************************************************************************/ + + +void SwCache::DeleteObj( SwCacheObj *pObj ) +{ + CHECK; + ASSERT( !pObj->IsLocked(), "SwCache::Delete: Object ist Locked." ); + if ( pObj->IsLocked() ) + return; + + if ( pFirst == pObj ) + { + if ( pFirst->GetNext() ) + pFirst = pFirst->GetNext(); + else + pFirst = pFirst->GetPrev(); + } + if ( pRealFirst == pObj ) + pRealFirst = pRealFirst->GetNext(); + if ( pLast == pObj ) + pLast = pLast->GetPrev(); + if ( pObj->GetPrev() ) + pObj->GetPrev()->SetNext( pObj->GetNext() ); + if ( pObj->GetNext() ) + pObj->GetNext()->SetPrev( pObj->GetPrev() ); + + aFreePositions.Insert( pObj->GetCachePos(), aFreePositions.Count() ); + *(pData + pObj->GetCachePos()) = (void*)0; + delete pObj; + + CHECK; + if ( Count() > nCurMax && + (nCurMax <= (Count() - aFreePositions.Count())) ) + { + //Falls moeglich wieder verkleinern, dazu muessen allerdings ausreichend + //Freie Positionen bereitstehen. + //Unangenehmer Nebeneffekt ist, das die Positionen verschoben werden + //muessen, und die Eigentuemer der Objekte diese wahrscheinlich nicht + //wiederfinden werden. + for ( USHORT i = 0; i < Count(); ++i ) + { + SwCacheObj *pObj = operator[](i); + if ( !pObj ) + { SwCacheObjArr::Remove( i, 1 ); + --i; + } + else + pObj->SetCachePos( i ); + } + aFreePositions.Remove( 0, aFreePositions.Count() ); + } + CHECK; +} + +/* + + +void SwCache::Delete( const void *pOwner, const USHORT nIndex ) +{ + INCREMENT( nDelete ); + SwCacheObj *pObj; + if ( 0 != (pObj = Get( pOwner, nIndex, FALSE )) ) + DeleteObj( pObj ); +} +*/ + + + +void SwCache::Delete( const void *pOwner ) +{ + INCREMENT( nDelete ); + SwCacheObj *pObj; + if ( 0 != (pObj = Get( pOwner, BOOL(FALSE) )) ) + DeleteObj( pObj ); +} + + +/************************************************************************* +|* +|* SwCache::Insert() +|* +|* Ersterstellung MA 15. Mar. 94 +|* Letzte Aenderung MA 20. Sep. 94 +|* +|*************************************************************************/ + + +BOOL SwCache::Insert( SwCacheObj *pNew ) +{ + CHECK; + ASSERT( !pNew->GetPrev() && !pNew->GetNext(), "New but not new." ); + + USHORT nPos;//Wird hinter den if's zum setzen am Obj benutzt. + if ( Count() < nCurMax ) + { + //Es ist noch Platz frei, also einfach einfuegen. + INCREMENT( nAppend ); + nPos = Count(); + SwCacheObjArr::C40_INSERT( SwCacheObj, pNew, nPos ); + } + else if ( aFreePositions.Count() ) + { + //Es exitieren Platzhalter, also den letzten benutzen. + INCREMENT( nInsertFree ); + const USHORT nFreePos = aFreePositions.Count() - 1; + nPos = aFreePositions[ nFreePos ]; + *(pData + nPos) = pNew; + aFreePositions.Remove( nFreePos ); + } + else + { + INCREMENT( nReplace ); + //Der letzte des LRU fliegt raus. + SwCacheObj *pObj = pLast; + + while ( pObj && pObj->IsLocked() ) + pObj = pObj->GetPrev(); + if ( !pObj ) + { + ASSERT( FALSE, "Cache overflow." ); + return FALSE; + } + + nPos = pObj->GetCachePos(); + if ( pObj == pLast ) + { ASSERT( pObj->GetPrev(), "Last but no Prev" ); + pLast = pObj->GetPrev(); + pLast->SetNext( 0 ); + } + else + { + if ( pObj->GetPrev() ) + pObj->GetPrev()->SetNext( pObj->GetNext() ); + if ( pObj->GetNext() ) + pObj->GetNext()->SetPrev( pObj->GetPrev() ); + } + delete pObj; + *(pData + nPos) = pNew; + } + pNew->SetCachePos( nPos ); + + //Anstelle von ToTop, einfach als pFirst einfuegen. +// ToTop( nPos ); + if ( pFirst ) + { + if ( pFirst->GetPrev() ) + { pFirst->GetPrev()->SetNext( pNew ); + pNew->SetPrev( pFirst->GetPrev() ); + } + pFirst->SetPrev( pNew ); + pNew->SetNext( pFirst ); + } + else + { ASSERT( !pLast, "Last but no First." ); + pLast = pNew; + } + if ( pFirst == pRealFirst ) + pRealFirst = pNew; + pFirst = pNew; + + CHECK; + return TRUE; +} + +/************************************************************************* +|* +|* SwCache::SetLRUOfst() +|* +|* Ersterstellung MA 15. Mar. 94 +|* Letzte Aenderung MA 15. Mar. 94 +|* +|*************************************************************************/ + + +void SwCache::SetLRUOfst( const USHORT nOfst ) +{ + if ( !pRealFirst || ((Count() - aFreePositions.Count()) < nOfst) ) + return; + + CHECK; + pFirst = pRealFirst; + for ( USHORT i = 0; i < Count() && i < nOfst; ++i ) + { + if ( pFirst->GetNext() && pFirst->GetNext()->GetNext() ) + pFirst = pFirst->GetNext(); + else + break; + } + CHECK; +} + +/************************************************************************* +|* +|* SwCacheObj::SwCacheObj() +|* +|* Ersterstellung MA 15. Mar. 94 +|* Letzte Aenderung MA 24. Nov. 95 +|* +|*************************************************************************/ + + +SwCacheObj::SwCacheObj( const void *pOwn ) : + nLock( 0 ), + nCachePos( USHRT_MAX ), + pNext( 0 ), + pPrev( 0 ), + pOwner( pOwn ) +{ +} + + + +SwCacheObj::~SwCacheObj() +{ +} + +/************************************************************************* +|* +|* SwCacheObj::SetLock(), Unlock() +|* +|* Ersterstellung MA 15. Mar. 94 +|* Letzte Aenderung MA 15. Mar. 94 +|* +|*************************************************************************/ + +#ifndef PRODUCT + + + +void SwCacheObj::Lock() +{ + ASSERT( nLock < UCHAR_MAX, "To many Locks for CacheObject." ); + ++nLock; +} + + + +void SwCacheObj::Unlock() +{ + ASSERT( nLock, "No more Locks available." ); + --nLock; +} +#endif + +/************************************************************************* +|* +|* SwCacheAccess::Get() +|* +|* Ersterstellung MA 15. Mar. 94 +|* Letzte Aenderung MA 04. Apr. 95 +|* +|*************************************************************************/ + + +void SwCacheAccess::_Get() +{ + ASSERT( !pObj, "SwCacheAcces Obj already available." ); + + pObj = NewObj(); + if ( !rCache.Insert( pObj ) ) + { + delete pObj; + pObj = 0; + } + else + pObj->Lock(); +} + +/************************************************************************* +|* +|* SwCacheAccess::IsAvailable() +|* +|* Ersterstellung MA 23. Mar. 94 +|* Letzte Aenderung MA 23. Mar. 94 +|* +|*************************************************************************/ + + +BOOL SwCacheAccess::IsAvailable() const +{ + return pObj != 0; +} + + + + + |