summaryrefslogtreecommitdiff
path: root/store/source/storcach.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'store/source/storcach.cxx')
-rw-r--r--store/source/storcach.cxx928
1 files changed, 414 insertions, 514 deletions
diff --git a/store/source/storcach.cxx b/store/source/storcach.cxx
index e6851eba1cc7..6306784592e0 100644
--- a/store/source/storcach.cxx
+++ b/store/source/storcach.cxx
@@ -31,634 +31,534 @@
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_store.hxx"
-#define _STORE_STORCACH_CXX "$Revision: 1.8 $"
-#include <sal/types.h>
-#include <rtl/alloc.h>
-#include <osl/diagnose.h>
-#include <osl/mutex.hxx>
-#include <store/types.h>
-#include <storbase.hxx>
-#ifndef _STORE_STORCACH_HXX_
-#include <storcach.hxx>
-#endif
+#include "storcach.hxx"
+
+#include "sal/types.h"
+#include "rtl/alloc.h"
+#include "osl/diagnose.h"
-#ifndef INCLUDED_CSTDDEF
-#include <cstddef>
-#define INCLUDED_CSTDDEF
+#include "store/types.h"
+#include "object.hxx"
+#include "storbase.hxx"
+
+#ifndef INCLUDED_STDDEF_H
+#include <stddef.h>
+#define INCLUDED_STDDEF_H
#endif
using namespace store;
/*========================================================================
*
- * OStorePageCacheEntry.
+ * PageCache (non-virtual interface) implementation.
*
*======================================================================*/
-namespace store
-{
-struct OStorePageCacheEntry
+storeError PageCache::lookupPageAt (PageHolder & rxPage, sal_uInt32 nOffset)
{
- typedef OStorePageCacheEntry self;
- typedef OStorePageData data;
- typedef OStorePageDescriptor D;
+ OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::PageCache::lookupPageAt(): invalid Offset");
+ if (nOffset == STORE_PAGE_NULL)
+ return store_E_CantSeek;
- /** Representation.
- */
- D m_aDescr;
- data *m_pData;
- self *m_pNext;
- self *m_pPrev;
+ return lookupPageAt_Impl (rxPage, nOffset);
+}
- /** Allocation.
- */
- static void * operator new (std::size_t n) SAL_THROW(())
- {
- return rtl_allocateMemory (sal_uInt32(n));
- }
- static void operator delete (void * p, std::size_t) SAL_THROW(())
- {
- rtl_freeMemory (p);
- }
+storeError PageCache::insertPageAt (PageHolder const & rxPage, sal_uInt32 nOffset)
+{
+ // [SECURITY:ValInput]
+ PageData const * pagedata = rxPage.get();
+ OSL_PRECOND(!(pagedata == 0), "store::PageCache::insertPageAt(): invalid Page");
+ if (pagedata == 0)
+ return store_E_InvalidParameter;
+
+ sal_uInt32 const offset = pagedata->location();
+ OSL_PRECOND(!(nOffset != offset), "store::PageCache::insertPageAt(): inconsistent Offset");
+ if (nOffset != offset)
+ return store_E_InvalidParameter;
+
+ OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::PageCache::insertPageAt(): invalid Offset");
+ if (nOffset == STORE_PAGE_NULL)
+ return store_E_CantSeek;
+
+ return insertPageAt_Impl (rxPage, nOffset);
+}
- /** Construction.
- */
- OStorePageCacheEntry (const D& rDescr, const data& rData)
- : m_aDescr (rDescr)
- {
- sal_uInt16 nSize = m_aDescr.m_nSize;
- m_pData = new(nSize) data(nSize);
- __store_memcpy (m_pData, &rData, nSize);
- m_pNext = m_pPrev = this;
- }
+storeError PageCache::updatePageAt (PageHolder const & rxPage, sal_uInt32 nOffset)
+{
+ // [SECURITY:ValInput]
+ PageData const * pagedata = rxPage.get();
+ OSL_PRECOND(!(pagedata == 0), "store::PageCache::updatePageAt(): invalid Page");
+ if (pagedata == 0)
+ return store_E_InvalidParameter;
+
+ sal_uInt32 const offset = pagedata->location();
+ OSL_PRECOND(!(nOffset != offset), "store::PageCache::updatePageAt(): inconsistent Offset");
+ if (nOffset != offset)
+ return store_E_InvalidParameter;
+
+ OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::PageCache::updatePageAt(): invalid Offset");
+ if (nOffset == STORE_PAGE_NULL)
+ return store_E_CantSeek;
+
+ return updatePageAt_Impl (rxPage, nOffset);
+}
- /** Data assignment.
- */
- void assign (const D& rDescr, const data& rData)
- {
- m_aDescr.m_nAddr = rDescr.m_nAddr;
- if (!(m_aDescr.m_nSize == rDescr.m_nSize))
- {
- delete m_pData;
- m_pData = new(rDescr.m_nSize) data(rDescr.m_nSize);
- m_aDescr.m_nSize = rDescr.m_nSize;
- }
- __store_memcpy (m_pData, &rData, m_aDescr.m_nSize);
- }
+storeError PageCache::removePageAt (sal_uInt32 nOffset)
+{
+ OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::PageCache::removePageAt(): invalid Offset");
+ if (nOffset == STORE_PAGE_NULL)
+ return store_E_CantSeek;
- /** Destruction.
- */
- ~OStorePageCacheEntry (void)
- {
- delete m_pData;
- }
+ return removePageAt_Impl (nOffset);
+}
- /** Comparison.
- */
- enum CompareResult
- {
- COMPARE_LESS = -1,
- COMPARE_EQUAL = 0,
- COMPARE_GREATER = 1
- };
+/*========================================================================
+ *
+ * Entry.
+ *
+ *======================================================================*/
+namespace
+{
- CompareResult compare (const D& rDescr) const
- {
- if (m_aDescr.m_nAddr == rDescr.m_nAddr)
- return COMPARE_EQUAL;
- if (m_aDescr.m_nAddr < rDescr.m_nAddr)
- return COMPARE_LESS;
- else
- return COMPARE_GREATER;
- }
+struct Entry
+{
+ /** Representation.
+ */
+ PageHolder m_xPage;
+ sal_uInt32 m_nOffset;
+ Entry * m_pNext;
- CompareResult compare (const self& rOther) const
- {
- return compare (rOther.m_aDescr);
- }
+ /** Allocation.
+ */
+ static void * operator new (size_t, void * p) { return p; }
+ static void operator delete (void *, void *) {}
- /** Address operation.
- */
- void invalidate (void)
- {
- m_aDescr.m_nAddr = STORE_PAGE_NULL;
- }
+ /** Construction.
+ */
+ explicit Entry (PageHolder const & rxPage = PageHolder(), sal_uInt32 nOffset = STORE_PAGE_NULL)
+ : m_xPage(rxPage), m_nOffset(nOffset), m_pNext(0)
+ {}
- sal_Bool isValid (void) const
- {
- return (m_aDescr.m_nAddr != STORE_PAGE_NULL);
- }
+ /** Destruction.
+ */
+ ~Entry() {}
+};
- /** Index operation.
- */
- sal_uInt16 index (void) const
- {
- return (m_aDescr.m_nUsed & 0x7fff);
- }
+} // namespace
- void index (sal_uInt16 nIndex)
- {
- m_aDescr.m_nUsed = ((m_aDescr.m_nUsed & 0x8000) | (nIndex & 0x7fff));
- }
+/*========================================================================
+ *
+ * EntryCache interface.
+ *
+ *======================================================================*/
+namespace
+{
- /** DirtyBit operation.
- */
- void clean (void)
- {
- m_aDescr.m_nUsed &= 0x7fff;
- }
+class EntryCache
+{
+ rtl_cache_type * m_entry_cache;
- void dirty (void)
- {
- m_aDescr.m_nUsed |= 0x8000;
- }
+public:
+ static EntryCache & get();
- sal_Bool isDirty (void) const
- {
- return ((m_aDescr.m_nUsed & 0x8000) == 0x8000);
- }
+ Entry * create (PageHolder const & rxPage, sal_uInt32 nOffset);
- /** List operation.
- */
- void backlink (self& rOther)
- {
- rOther.m_pNext = this;
- rOther.m_pPrev = m_pPrev;
- m_pPrev = &rOther;
- rOther.m_pPrev->m_pNext = &rOther;
- }
+ void destroy (Entry * entry);
- void unlink (void)
- {
- m_pNext->m_pPrev = m_pPrev;
- m_pPrev->m_pNext = m_pNext;
- m_pNext = this;
- m_pPrev = this;
- }
+protected:
+ EntryCache();
+ ~EntryCache();
};
-} // namespace store
+} // namespace
/*========================================================================
*
- * OStorePageCache debug internals.
+ * EntryCache implementation.
*
*======================================================================*/
-#ifdef __STORE_CACHE_DEBUG
-/*
- * __store_check_entry.
- */
-static sal_Bool __store_check_entry (
- OStorePageCacheEntry **ppData, sal_uInt16 nUsed)
+EntryCache & EntryCache::get()
+{
+ static EntryCache g_entry_cache;
+ return g_entry_cache;
+}
+
+EntryCache::EntryCache()
{
- if (nUsed > 1)
+ m_entry_cache = rtl_cache_create (
+ "store_cache_entry_cache",
+ sizeof(Entry),
+ 0, // objalign
+ 0, // constructor
+ 0, // destructor
+ 0, // reclaim
+ 0, // userarg
+ 0, // default source
+ 0 // flags
+ );
+}
+
+EntryCache::~EntryCache()
+{
+ rtl_cache_destroy (m_entry_cache), m_entry_cache = 0;
+}
+
+Entry * EntryCache::create (PageHolder const & rxPage, sal_uInt32 nOffset)
+{
+ void * pAddr = rtl_cache_alloc (m_entry_cache);
+ if (pAddr != 0)
{
- for (sal_uInt16 i = 0; i < nUsed - 1; i++)
- {
- sal_uInt32 ai = ppData[i ]->m_aDescr.m_nAddr;
- sal_uInt32 ak = ppData[i + 1]->m_aDescr.m_nAddr;
- if (!(ai <= ak))
- return sal_False;
- if (!(i == ppData[i]->index()))
- return sal_False;
- }
+ // construct.
+ return new(pAddr) Entry (rxPage, nOffset);
}
- return sal_True;
+ return 0;
}
-/*
- * __store_find_entry.
- */
-static sal_uInt16 __store_find_entry (
- const OStorePageDescriptor &rDescr,
- const OStorePageCacheEntry *pHead)
+void EntryCache::destroy (Entry * entry)
{
- if (pHead)
+ if (entry != 0)
{
- if (pHead->m_aDescr.m_nAddr == rDescr.m_nAddr)
- return pHead->index();
+ // destruct.
+ entry->~Entry();
- OStorePageCacheEntry *pEntry = pHead->m_pNext;
- while (pEntry != pHead)
- {
- if (pEntry->m_aDescr.m_nAddr == rDescr.m_nAddr)
- return pEntry->index();
- else
- pEntry = pEntry->m_pNext;
- }
+ // return to cache.
+ rtl_cache_free (m_entry_cache, entry);
}
- return ((sal_uInt16)(-1));
}
-#endif /* __STORE_CACHE_DEBUG */
-
/*========================================================================
*
- * OStorePageCache implementation.
- *
- * (two-way association (sorted address array, LRU chain)).
- * (external OStorePageData representation).
+ * highbit():= log2() + 1 (complexity O(1))
*
*======================================================================*/
-/*
- * Allocation.
- */
-void * OStorePageCache::operator new (std::size_t n) SAL_THROW(())
+static int highbit(sal_Size n)
{
- return rtl_allocateMemory (sal_uInt32(n));
-}
+ register int k = 1;
-void OStorePageCache::operator delete (void * p, std::size_t) SAL_THROW(())
-{
- rtl_freeMemory (p);
+ if (n == 0)
+ return (0);
+#if SAL_TYPES_SIZEOFLONG == 8
+ if (n & 0xffffffff00000000ul)
+ k |= 32, n >>= 32;
+#endif
+ if (n & 0xffff0000)
+ k |= 16, n >>= 16;
+ if (n & 0xff00)
+ k |= 8, n >>= 8;
+ if (n & 0xf0)
+ k |= 4, n >>= 4;
+ if (n & 0x0c)
+ k |= 2, n >>= 2;
+ if (n & 0x02)
+ k++;
+
+ return (k);
}
-/*
- * OStorePageCache.
- */
-OStorePageCache::OStorePageCache (sal_uInt16 nPages)
- : m_nSize (STORE_LIMIT_CACHEPAGES),
- m_nUsed (0),
- m_pHead (0),
- m_nHit (0),
- m_nMissed (0),
- m_nUpdHit (0),
- m_nUpdLRU (0),
- m_nWrtBack (0)
+/*========================================================================
+ *
+ * PageCache_Impl implementation.
+ *
+ *======================================================================*/
+namespace store
{
- for (sal_uInt16 i = 0; i < m_nSize; i++)
- m_pData[i] = NULL;
- if (nPages < m_nSize)
- m_nSize = nPages;
-}
-/*
- * ~OStorePageCache.
- */
-OStorePageCache::~OStorePageCache (void)
+class PageCache_Impl :
+ public store::OStoreObject,
+ public store::PageCache
{
-#if OSL_DEBUG_LEVEL > 1
- double x = hitRatio();
- x = 0;
-#endif /* OSL_DEBUG_LEVEL > 1 */
+ /** Representation.
+ */
+ static size_t const theTableSize = 32;
+ STORE_STATIC_ASSERT(STORE_IMPL_ISP2(theTableSize));
- for (sal_uInt16 i = 0; i < m_nSize; i++)
- delete m_pData[i];
-}
+ Entry ** m_hash_table;
+ Entry * m_hash_table_0[theTableSize];
+ size_t m_hash_size;
+ size_t m_hash_shift;
+ size_t const m_page_shift;
-/*
- * find.
- */
-sal_uInt16 OStorePageCache::find (const OStorePageDescriptor &rDescr) const
-{
- register sal_Int32 l = 0;
- register sal_Int32 r = m_nUsed - 1;
+ size_t m_hash_entries; // total number of entries in table.
+ size_t m_nHit;
+ size_t m_nMissed;
- while (l < r)
+ inline int hash_Impl(sal_uInt32 a, size_t s, size_t q, size_t m)
{
- register sal_Int32 m = ((l + r) >> 1);
-
- if (m_pData[m]->m_aDescr.m_nAddr == rDescr.m_nAddr)
- return ((sal_uInt16)(m));
- if (m_pData[m]->m_aDescr.m_nAddr < rDescr.m_nAddr)
- l = m + 1;
- else
- r = m - 1;
+ return ((((a) + ((a) >> (s)) + ((a) >> ((s) << 1))) >> (q)) & (m));
}
+ inline int hash_index_Impl (sal_uInt32 nOffset)
+ {
+ return hash_Impl(nOffset, m_hash_shift, m_page_shift, m_hash_size - 1);
+ }
+
+ Entry * lookup_Impl (Entry * entry, sal_uInt32 nOffset);
+ void rescale_Impl (sal_Size new_size);
+
+ /** PageCache Implementation.
+ */
+ virtual storeError lookupPageAt_Impl (
+ PageHolder & rxPage,
+ sal_uInt32 nOffset);
+
+ virtual storeError insertPageAt_Impl (
+ PageHolder const & rxPage,
+ sal_uInt32 nOffset);
+
+ virtual storeError updatePageAt_Impl (
+ PageHolder const & rxPage,
+ sal_uInt32 nOffset);
+
+ virtual storeError removePageAt_Impl (
+ sal_uInt32 nOffset);
+
+ /** Not implemented.
+ */
+ PageCache_Impl (PageCache_Impl const &);
+ PageCache_Impl & operator= (PageCache_Impl const &);
+
+public:
+ /** Construction.
+ */
+ explicit PageCache_Impl (sal_uInt16 nPageSize);
+
+ /** Delegate multiple inherited IReference.
+ */
+ virtual oslInterlockedCount SAL_CALL acquire();
+ virtual oslInterlockedCount SAL_CALL release();
+
+protected:
+ /** Destruction.
+ */
+ virtual ~PageCache_Impl (void);
+};
+
+} // namespace store
- // Match or insert position. Caller must do final compare.
- return ((sal_uInt16)(r));
+PageCache_Impl::PageCache_Impl (sal_uInt16 nPageSize)
+ : m_hash_table (m_hash_table_0),
+ m_hash_size (theTableSize),
+ m_hash_shift (highbit(m_hash_size) - 1),
+ m_page_shift (highbit(nPageSize) - 1),
+ m_hash_entries (0),
+ m_nHit (0),
+ m_nMissed (0)
+{
+ static size_t const theSize = sizeof(m_hash_table_0) / sizeof(m_hash_table_0[0]);
+ STORE_STATIC_ASSERT(theSize == theTableSize);
+ memset(m_hash_table_0, 0, sizeof(m_hash_table_0));
}
-/*
- * move.
- */
-void OStorePageCache::move (sal_uInt16 nSI, sal_uInt16 nDI)
+PageCache_Impl::~PageCache_Impl()
{
- entry *p = m_pData[nSI];
- if (nSI < nDI)
+ double s_x = 0.0, s_xx = 0.0;
+ sal_Size i, n = m_hash_size;
+ for (i = 0; i < n; i++)
{
- // shift left.
- __store_memmove (
- &m_pData[nSI ],
- &m_pData[nSI + 1],
- (nDI - nSI) * sizeof(entry*));
-
- // re-index.
- for (sal_uInt16 i = nSI; i < nDI; i++)
- m_pData[i]->index(i);
+ int x = 0;
+ Entry * entry = m_hash_table[i];
+ while (entry != 0)
+ {
+ m_hash_table[i] = entry->m_pNext, entry->m_pNext = 0;
+ EntryCache::get().destroy (entry);
+ entry = m_hash_table[i];
+ x += 1;
+ }
+ s_x += double(x);
+ s_xx += double(x) * double(x);
}
- if (nSI > nDI)
+ double ave = s_x / double(n);
+ OSL_TRACE("ave hash chain length: %g", ave);
+ (void) ave;
+
+ if (m_hash_table != m_hash_table_0)
{
- // shift right.
- __store_memmove (
- &m_pData[nDI + 1],
- &m_pData[nDI ],
- (nSI - nDI) * sizeof(entry*));
-
- // re-index.
- for (sal_uInt16 i = nSI; i > nDI; i--)
- m_pData[i]->index(i);
+ rtl_freeMemory (m_hash_table);
+ m_hash_table = m_hash_table_0;
+ m_hash_size = theTableSize;
+ m_hash_shift = highbit(m_hash_size) - 1;
}
- m_pData[nDI] = p;
- m_pData[nDI]->index(nDI);
-
-#ifdef __STORE_CACHE_DEBUG
- OSL_POSTCOND(
- __store_check_entry(&m_pData[0], m_nUsed),
- "OStorePageCache::move(): check_entry() failed");
-#endif /* __STORE_CACHE_DEBUG */
+ OSL_TRACE("Hits: %u, Misses: %u", m_nHit, m_nMissed);
}
-/*
- * insert.
- */
-storeError OStorePageCache::insert (
- sal_uInt16 nDI,
- const OStorePageDescriptor &rDescr,
- const OStorePageData &rData,
- OStorePageBIOS &rBIOS,
- InsertMode eMode)
+oslInterlockedCount PageCache_Impl::acquire()
{
-#ifdef __STORE_CACHE_DEBUG
- OSL_PRECOND(
- __store_check_entry(&m_pData[0], m_nUsed),
- "OStorePageCache::insert(): check_entry() failed");
-#endif /* __STORE_CACHE_DEBUG */
-
- entry::CompareResult result = entry::COMPARE_EQUAL;
- if (nDI < m_nUsed)
- {
- result = m_pData[nDI]->compare (rDescr);
- if (result == entry::COMPARE_LESS)
- nDI += 1;
- }
+ return OStoreObject::acquire();
+}
- if (nDI == (sal_uInt16)(-1))
- nDI = 0;
- if (nDI == m_nSize)
- nDI -= 1;
+oslInterlockedCount PageCache_Impl::release()
+{
+ return OStoreObject::release();
+}
- if (m_nUsed < m_nSize)
- {
- // Allocate cache entry.
- m_pData[m_nUsed] = new entry (rDescr, rData);
- move (m_nUsed, nDI);
- m_nUsed++;
-
- // Update LRU.
- if (m_pHead)
- m_pHead->backlink (*m_pData[nDI]);
- m_pHead = m_pData[nDI];
- }
- else
+void PageCache_Impl::rescale_Impl (sal_Size new_size)
+{
+ sal_Size new_bytes = new_size * sizeof(Entry*);
+ Entry ** new_table = (Entry**)(rtl_allocateMemory(new_bytes));
+
+ if (new_table != 0)
{
- // Check for invalidated cache entry.
- sal_uInt16 nSI = m_nUsed - 1;
- if (m_pData[nSI]->isValid())
- {
- // Replace least recently used cache entry.
- m_nUpdLRU++;
+ Entry ** old_table = m_hash_table;
+ sal_Size old_size = m_hash_size;
- m_pHead = m_pHead->m_pPrev;
- nSI = m_pHead->index();
+ OSL_TRACE("ave chain length: %u, total entries: %u [old_size: %u, new_size: %u]",
+ m_hash_entries >> m_hash_shift, m_hash_entries, old_size, new_size);
- // Check DirtyBit.
- if (m_pHead->isDirty())
- {
- // Save PageDescriptor.
- OStorePageDescriptor aDescr (m_pHead->m_aDescr);
-
- // Write page.
- storeError eErrCode = rBIOS.write (
- aDescr.m_nAddr, m_pHead->m_pData, aDescr.m_nSize);
- if (eErrCode != store_E_None)
- return eErrCode;
-
- // Mark as clean.
- m_pHead->clean();
- m_nWrtBack++;
- }
- }
- else
+ memset (new_table, 0, new_bytes);
+
+ m_hash_table = new_table;
+ m_hash_size = new_size;
+ m_hash_shift = highbit(m_hash_size) - 1;
+
+ sal_Size i;
+ for (i = 0; i < old_size; i++)
{
- // Replace invalidated cache entry. Check LRU.
- if (!(m_pData[nSI] == m_pHead))
+ Entry * curr = old_table[i];
+ while (curr != 0)
{
- // Update LRU.
- m_pData[nSI]->unlink();
- m_pHead->backlink (*m_pData[nSI]);
- m_pHead = m_pData[nSI];
+ Entry * next = curr->m_pNext;
+ int index = hash_index_Impl(curr->m_nOffset);
+ curr->m_pNext = m_hash_table[index], m_hash_table[index] = curr;
+ curr = next;
}
+ old_table[i] = 0;
}
-
- // Check source and destination indices.
- if (nSI < nDI)
+ if (old_table != m_hash_table_0)
{
- result = m_pData[nDI]->compare(rDescr);
- if (result == entry::COMPARE_GREATER)
- nDI -= 1;
+ //
+ rtl_freeMemory (old_table);
}
-
- // Assign data.
- m_pData[nSI]->assign (rDescr, rData);
- move (nSI, nDI);
}
-
- // Check InsertMode.
- if (eMode == INSERT_CLEAN)
- m_pHead->clean();
- else
- m_pHead->dirty();
-
- // Done.
- return store_E_None;
}
-/*
- * load.
- */
-storeError OStorePageCache::load (
- const OStorePageDescriptor &rDescr,
- OStorePageData &rData,
- OStorePageBIOS &rBIOS,
- osl::Mutex *pMutex)
+Entry * PageCache_Impl::lookup_Impl (Entry * entry, sal_uInt32 nOffset)
{
- // Enter.
- STORE_METHOD_ENTER(pMutex);
-
- // Find cache index.
- sal_uInt16 i = find (rDescr);
- if (i < m_nUsed)
+ register int lookups = 0;
+ while (entry != 0)
{
- if (m_pData[i]->compare(rDescr) == entry::COMPARE_EQUAL)
- {
- // Cache hit.
- m_nHit++;
-
- if (!(m_pData[i] == m_pHead))
- {
- // Update LRU.
- m_pData[i]->unlink();
- m_pHead->backlink (*m_pData[i]);
- m_pHead = m_pData[i];
- }
+ if (entry->m_nOffset == nOffset)
+ break;
- // Load data and Leave.
- __store_memcpy (&rData, m_pHead->m_pData, rDescr.m_nSize);
- STORE_METHOD_LEAVE(pMutex, store_E_None);
- }
+ lookups += 1;
+ entry = entry->m_pNext;
}
+ if (lookups > 2)
+ {
+ sal_Size new_size = m_hash_size, ave = m_hash_entries >> m_hash_shift;
+ for (; ave > 4; new_size *= 2, ave /= 2)
+ continue;
+ if (new_size != m_hash_size)
+ rescale_Impl (new_size);
+ }
+ return entry;
+}
- // Cache miss.
- m_nMissed++;
-
- // Load data.
- storeError eErrCode = rBIOS.read (
- rDescr.m_nAddr, &rData, rDescr.m_nSize);
- if (eErrCode != store_E_None)
- STORE_METHOD_LEAVE(pMutex, eErrCode);
+storeError PageCache_Impl::lookupPageAt_Impl (
+ PageHolder & rxPage,
+ sal_uInt32 nOffset)
+{
+ int index = hash_index_Impl(nOffset);
+ Entry const * entry = lookup_Impl (m_hash_table[index], nOffset);
+ if (entry != 0)
+ {
+ // Existing entry.
+ rxPage = entry->m_xPage;
- // Insert data.
- eErrCode = insert (i, rDescr, rData, rBIOS, INSERT_CLEAN);
- if (eErrCode != store_E_None)
- STORE_METHOD_LEAVE(pMutex, eErrCode);
+ // Update stats and leave.
+ m_nHit += 1;
+ return store_E_None;
+ }
- // Leave with pending verification.
- STORE_METHOD_LEAVE(pMutex, store_E_Pending);
+ // Cache miss. Update stats and leave.
+ m_nMissed += 1;
+ return store_E_NotExists;
}
-/*
- * update.
- */
-storeError OStorePageCache::update (
- const OStorePageDescriptor &rDescr,
- const OStorePageData &rData,
- OStorePageBIOS &rBIOS,
- osl::Mutex *pMutex,
- UpdateMode eMode)
+storeError PageCache_Impl::insertPageAt_Impl (
+ PageHolder const & rxPage,
+ sal_uInt32 nOffset)
{
- // Enter.
- STORE_METHOD_ENTER(pMutex);
-
- // Check UpdateMode.
- if (eMode == UPDATE_WRITE_THROUGH)
+ Entry * entry = EntryCache::get().create (rxPage, nOffset);
+ if (entry != 0)
{
- // Save data.
- storeError eErrCode = rBIOS.write (
- rDescr.m_nAddr, &rData, rDescr.m_nSize);
- if (eErrCode != store_E_None)
- STORE_METHOD_LEAVE(pMutex, eErrCode);
- m_nWrtBack++;
+ // Insert new entry.
+ int index = hash_index_Impl(nOffset);
+ entry->m_pNext = m_hash_table[index], m_hash_table[index] = entry;
+
+ // Update stats and leave.
+ m_hash_entries += 1;
+ return store_E_None;
}
+ return store_E_OutOfMemory;
+}
- // Find cache index.
- sal_uInt16 i = find (rDescr);
- if (i < m_nUsed)
+storeError PageCache_Impl::updatePageAt_Impl (
+ PageHolder const & rxPage,
+ sal_uInt32 nOffset)
+{
+ int index = hash_index_Impl(nOffset);
+ Entry * entry = lookup_Impl (m_hash_table[index], nOffset);
+ if (entry != 0)
{
- if (m_pData[i]->compare(rDescr) == entry::COMPARE_EQUAL)
- {
- // Cache hit. Check LRU.
- m_nUpdHit++;
- if (!(m_pData[i] == m_pHead))
- {
- // Update LRU.
- m_pData[i]->unlink();
- m_pHead->backlink (*m_pData[i]);
- m_pHead = m_pData[i];
- }
+ // Update existing entry.
+ entry->m_xPage = rxPage;
- // Check UpdateMode.
- if (eMode == UPDATE_WRITE_THROUGH)
- m_pHead->clean();
- else
- m_pHead->dirty();
-
- // Update data and leave.
- __store_memcpy (m_pHead->m_pData, &rData, rDescr.m_nSize);
- STORE_METHOD_LEAVE(pMutex, store_E_None);
- }
+ // Update stats and leave. // m_nUpdHit += 1;
+ return store_E_None;
}
-
- // Cache miss. Insert data and leave.
- storeError eErrCode = insert (
- i, rDescr, rData, rBIOS,
- ((eMode == UPDATE_WRITE_THROUGH) ? INSERT_CLEAN : INSERT_DIRTY));
- STORE_METHOD_LEAVE(pMutex, eErrCode);
+ return insertPageAt_Impl (rxPage, nOffset);
}
-/*
- * invalidate.
- */
-storeError OStorePageCache::invalidate (
- const OStorePageDescriptor &rDescr,
- osl::Mutex *pMutex)
+storeError PageCache_Impl::removePageAt_Impl (
+ sal_uInt32 nOffset)
{
- // Enter.
- STORE_METHOD_ENTER(pMutex);
-
- // Find cache index.
- sal_uInt16 i = find (rDescr);
- if (i < m_nUsed)
+ Entry ** ppEntry = &(m_hash_table[hash_index_Impl(nOffset)]);
+ while (*ppEntry != 0)
{
- if (m_pData[i]->compare(rDescr) == entry::COMPARE_EQUAL)
+ if ((*ppEntry)->m_nOffset == nOffset)
{
- // Cache hit. Update LRU.
- if (!(m_pData[i] == m_pHead))
- {
- m_pData[i]->unlink();
- m_pHead->backlink (*m_pData[i]);
- }
- else
- {
- m_pHead = m_pHead->m_pNext;
- }
+ // Existing entry.
+ Entry * entry = (*ppEntry);
- // Invalidate.
- m_pData[i]->clean();
- m_pData[i]->invalidate();
- move (i, m_nUsed - 1);
+ // Dequeue and destroy entry.
+ (*ppEntry) = entry->m_pNext, entry->m_pNext = 0;
+ EntryCache::get().destroy (entry);
+
+ // Update stats and leave.
+ m_hash_entries -= 1;
+ return store_E_None;
}
+ ppEntry = &((*ppEntry)->m_pNext);
}
-
- // Leave.
- STORE_METHOD_LEAVE(pMutex, store_E_None);
+ return store_E_NotExists;
}
-/*
- * flush.
- */
-storeError OStorePageCache::flush (
- OStorePageBIOS &rBIOS,
- osl::Mutex *pMutex)
-{
- // Enter.
- STORE_METHOD_ENTER(pMutex);
+/*========================================================================
+ *
+ * Old OStorePageCache implementation.
+ *
+ * (two-way association (sorted address array, LRU chain)).
+ * (external OStorePageData representation).
+ *
+ *======================================================================*/
- // Check all entries.
- for (sal_uInt16 i = 0; i < m_nUsed; i++)
- {
- // Check for dirty entry.
- if (m_pData[i]->isDirty() && m_pData[i]->isValid())
- {
- // Save PageDescriptor.
- OStorePageDescriptor aDescr (m_pData[i]->m_aDescr);
-
- // Write page.
- storeError eErrCode = rBIOS.write (
- aDescr.m_nAddr, m_pData[i]->m_pData, aDescr.m_nSize);
- OSL_POSTCOND(
- eErrCode == store_E_None,
- "OStorePageCache::flush(): write() failed");
-
- // Mark entry clean.
- if (eErrCode == store_E_None)
- m_pData[i]->clean();
- m_nWrtBack++;
- }
- }
+/*========================================================================
+ *
+ * PageCache factory implementation.
+ *
+ *======================================================================*/
+namespace store {
+
+storeError
+PageCache_createInstance (
+ rtl::Reference< store::PageCache > & rxCache,
+ sal_uInt16 nPageSize)
+{
+ rxCache = new PageCache_Impl (nPageSize);
+ if (!rxCache.is())
+ return store_E_OutOfMemory;
- // Leave.
- STORE_METHOD_LEAVE(pMutex, store_E_None);
+ return store_E_None;
}
+
+} // namespace store