xref: /aoo42x/main/store/source/storcach.cxx (revision c1e8cc3a)
173d9b18aSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
373d9b18aSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
473d9b18aSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
573d9b18aSAndrew Rist  * distributed with this work for additional information
673d9b18aSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
773d9b18aSAndrew Rist  * to you under the Apache License, Version 2.0 (the
873d9b18aSAndrew Rist  * "License"); you may not use this file except in compliance
973d9b18aSAndrew Rist  * with the License.  You may obtain a copy of the License at
1073d9b18aSAndrew Rist  *
1173d9b18aSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
1273d9b18aSAndrew Rist  *
1373d9b18aSAndrew Rist  * Unless required by applicable law or agreed to in writing,
1473d9b18aSAndrew Rist  * software distributed under the License is distributed on an
1573d9b18aSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1673d9b18aSAndrew Rist  * KIND, either express or implied.  See the License for the
1773d9b18aSAndrew Rist  * specific language governing permissions and limitations
1873d9b18aSAndrew Rist  * under the License.
1973d9b18aSAndrew Rist  *
2073d9b18aSAndrew Rist  *************************************************************/
2173d9b18aSAndrew Rist 
2273d9b18aSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_store.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "storcach.hxx"
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include "sal/types.h"
30cdf0e10cSrcweir #include "rtl/alloc.h"
31cdf0e10cSrcweir #include "osl/diagnose.h"
32cdf0e10cSrcweir 
33cdf0e10cSrcweir #include "store/types.h"
34cdf0e10cSrcweir #include "object.hxx"
35cdf0e10cSrcweir #include "storbase.hxx"
36cdf0e10cSrcweir 
37cdf0e10cSrcweir #ifndef INCLUDED_STDDEF_H
38cdf0e10cSrcweir #include <stddef.h>
39cdf0e10cSrcweir #define INCLUDED_STDDEF_H
40cdf0e10cSrcweir #endif
41cdf0e10cSrcweir 
42cdf0e10cSrcweir using namespace store;
43cdf0e10cSrcweir 
44cdf0e10cSrcweir /*========================================================================
45cdf0e10cSrcweir  *
46cdf0e10cSrcweir  * PageCache (non-virtual interface) implementation.
47cdf0e10cSrcweir  *
48cdf0e10cSrcweir  *======================================================================*/
49cdf0e10cSrcweir 
lookupPageAt(PageHolder & rxPage,sal_uInt32 nOffset)50cdf0e10cSrcweir storeError PageCache::lookupPageAt (PageHolder & rxPage, sal_uInt32 nOffset)
51cdf0e10cSrcweir {
52cdf0e10cSrcweir     OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::PageCache::lookupPageAt(): invalid Offset");
53cdf0e10cSrcweir     if (nOffset == STORE_PAGE_NULL)
54cdf0e10cSrcweir         return store_E_CantSeek;
55cdf0e10cSrcweir 
56cdf0e10cSrcweir     return lookupPageAt_Impl (rxPage, nOffset);
57cdf0e10cSrcweir }
58cdf0e10cSrcweir 
insertPageAt(PageHolder const & rxPage,sal_uInt32 nOffset)59cdf0e10cSrcweir storeError PageCache::insertPageAt (PageHolder const & rxPage, sal_uInt32 nOffset)
60cdf0e10cSrcweir {
61cdf0e10cSrcweir     // [SECURITY:ValInput]
62cdf0e10cSrcweir     PageData const * pagedata = rxPage.get();
63cdf0e10cSrcweir     OSL_PRECOND(!(pagedata == 0), "store::PageCache::insertPageAt(): invalid Page");
64cdf0e10cSrcweir     if (pagedata == 0)
65cdf0e10cSrcweir         return store_E_InvalidParameter;
66cdf0e10cSrcweir 
67cdf0e10cSrcweir     sal_uInt32 const offset = pagedata->location();
68cdf0e10cSrcweir     OSL_PRECOND(!(nOffset != offset), "store::PageCache::insertPageAt(): inconsistent Offset");
69cdf0e10cSrcweir     if (nOffset != offset)
70cdf0e10cSrcweir         return store_E_InvalidParameter;
71cdf0e10cSrcweir 
72cdf0e10cSrcweir     OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::PageCache::insertPageAt(): invalid Offset");
73cdf0e10cSrcweir     if (nOffset == STORE_PAGE_NULL)
74cdf0e10cSrcweir         return store_E_CantSeek;
75cdf0e10cSrcweir 
76cdf0e10cSrcweir     return insertPageAt_Impl (rxPage, nOffset);
77cdf0e10cSrcweir }
78cdf0e10cSrcweir 
updatePageAt(PageHolder const & rxPage,sal_uInt32 nOffset)79cdf0e10cSrcweir storeError PageCache::updatePageAt (PageHolder const & rxPage, sal_uInt32 nOffset)
80cdf0e10cSrcweir {
81cdf0e10cSrcweir     // [SECURITY:ValInput]
82cdf0e10cSrcweir     PageData const * pagedata = rxPage.get();
83cdf0e10cSrcweir     OSL_PRECOND(!(pagedata == 0), "store::PageCache::updatePageAt(): invalid Page");
84cdf0e10cSrcweir     if (pagedata == 0)
85cdf0e10cSrcweir         return store_E_InvalidParameter;
86cdf0e10cSrcweir 
87cdf0e10cSrcweir     sal_uInt32 const offset = pagedata->location();
88cdf0e10cSrcweir     OSL_PRECOND(!(nOffset != offset), "store::PageCache::updatePageAt(): inconsistent Offset");
89cdf0e10cSrcweir     if (nOffset != offset)
90cdf0e10cSrcweir         return store_E_InvalidParameter;
91cdf0e10cSrcweir 
92cdf0e10cSrcweir     OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::PageCache::updatePageAt(): invalid Offset");
93cdf0e10cSrcweir     if (nOffset == STORE_PAGE_NULL)
94cdf0e10cSrcweir         return store_E_CantSeek;
95cdf0e10cSrcweir 
96cdf0e10cSrcweir     return updatePageAt_Impl (rxPage, nOffset);
97cdf0e10cSrcweir }
98cdf0e10cSrcweir 
removePageAt(sal_uInt32 nOffset)99cdf0e10cSrcweir storeError PageCache::removePageAt (sal_uInt32 nOffset)
100cdf0e10cSrcweir {
101cdf0e10cSrcweir     OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::PageCache::removePageAt(): invalid Offset");
102cdf0e10cSrcweir     if (nOffset == STORE_PAGE_NULL)
103cdf0e10cSrcweir         return store_E_CantSeek;
104cdf0e10cSrcweir 
105cdf0e10cSrcweir     return removePageAt_Impl (nOffset);
106cdf0e10cSrcweir }
107cdf0e10cSrcweir 
108cdf0e10cSrcweir /*========================================================================
109cdf0e10cSrcweir  *
110cdf0e10cSrcweir  * Entry.
111cdf0e10cSrcweir  *
112cdf0e10cSrcweir  *======================================================================*/
113cdf0e10cSrcweir namespace
114cdf0e10cSrcweir {
115cdf0e10cSrcweir 
116cdf0e10cSrcweir struct Entry
117cdf0e10cSrcweir {
118cdf0e10cSrcweir     /** Representation.
119cdf0e10cSrcweir      */
120cdf0e10cSrcweir     PageHolder m_xPage;
121cdf0e10cSrcweir     sal_uInt32 m_nOffset;
122cdf0e10cSrcweir     Entry *    m_pNext;
123cdf0e10cSrcweir 
124cdf0e10cSrcweir     /** Allocation.
125cdf0e10cSrcweir      */
operator new__anonf13d188b0111::Entry126cdf0e10cSrcweir     static void * operator new (size_t, void * p) { return p; }
operator delete__anonf13d188b0111::Entry127cdf0e10cSrcweir     static void   operator delete (void *, void *) {}
128cdf0e10cSrcweir 
129cdf0e10cSrcweir     /** Construction.
130cdf0e10cSrcweir      */
Entry__anonf13d188b0111::Entry131cdf0e10cSrcweir     explicit Entry (PageHolder const & rxPage = PageHolder(), sal_uInt32 nOffset = STORE_PAGE_NULL)
132cdf0e10cSrcweir         : m_xPage(rxPage), m_nOffset(nOffset), m_pNext(0)
133cdf0e10cSrcweir     {}
134cdf0e10cSrcweir 
135cdf0e10cSrcweir     /** Destruction.
136cdf0e10cSrcweir      */
~Entry__anonf13d188b0111::Entry137cdf0e10cSrcweir     ~Entry() {}
138cdf0e10cSrcweir };
139cdf0e10cSrcweir 
140cdf0e10cSrcweir } // namespace
141cdf0e10cSrcweir 
142cdf0e10cSrcweir /*========================================================================
143cdf0e10cSrcweir  *
144cdf0e10cSrcweir  * EntryCache interface.
145cdf0e10cSrcweir  *
146cdf0e10cSrcweir  *======================================================================*/
147cdf0e10cSrcweir namespace
148cdf0e10cSrcweir {
149cdf0e10cSrcweir 
150cdf0e10cSrcweir class EntryCache
151cdf0e10cSrcweir {
152cdf0e10cSrcweir     rtl_cache_type * m_entry_cache;
153cdf0e10cSrcweir 
154cdf0e10cSrcweir public:
155cdf0e10cSrcweir     static EntryCache & get();
156cdf0e10cSrcweir 
157cdf0e10cSrcweir     Entry * create (PageHolder const & rxPage, sal_uInt32 nOffset);
158cdf0e10cSrcweir 
159cdf0e10cSrcweir     void destroy (Entry * entry);
160cdf0e10cSrcweir 
161cdf0e10cSrcweir protected:
162cdf0e10cSrcweir     EntryCache();
163cdf0e10cSrcweir     ~EntryCache();
164cdf0e10cSrcweir };
165cdf0e10cSrcweir 
166cdf0e10cSrcweir } // namespace
167cdf0e10cSrcweir 
168cdf0e10cSrcweir /*========================================================================
169cdf0e10cSrcweir  *
170cdf0e10cSrcweir  * EntryCache implementation.
171cdf0e10cSrcweir  *
172cdf0e10cSrcweir  *======================================================================*/
173cdf0e10cSrcweir 
get()174cdf0e10cSrcweir EntryCache & EntryCache::get()
175cdf0e10cSrcweir {
176cdf0e10cSrcweir     static EntryCache g_entry_cache;
177cdf0e10cSrcweir     return g_entry_cache;
178cdf0e10cSrcweir }
179cdf0e10cSrcweir 
EntryCache()180cdf0e10cSrcweir EntryCache::EntryCache()
181cdf0e10cSrcweir {
182cdf0e10cSrcweir     m_entry_cache = rtl_cache_create (
183cdf0e10cSrcweir         "store_cache_entry_cache",
184cdf0e10cSrcweir         sizeof(Entry),
185cdf0e10cSrcweir         0, // objalign
186cdf0e10cSrcweir         0, // constructor
187cdf0e10cSrcweir         0, // destructor
188cdf0e10cSrcweir         0, // reclaim
189cdf0e10cSrcweir         0, // userarg
190cdf0e10cSrcweir         0, // default source
191cdf0e10cSrcweir         0  // flags
192cdf0e10cSrcweir         );
193cdf0e10cSrcweir }
194cdf0e10cSrcweir 
~EntryCache()195cdf0e10cSrcweir EntryCache::~EntryCache()
196cdf0e10cSrcweir {
197cdf0e10cSrcweir     rtl_cache_destroy (m_entry_cache), m_entry_cache = 0;
198cdf0e10cSrcweir }
199cdf0e10cSrcweir 
create(PageHolder const & rxPage,sal_uInt32 nOffset)200cdf0e10cSrcweir Entry * EntryCache::create (PageHolder const & rxPage, sal_uInt32 nOffset)
201cdf0e10cSrcweir {
202cdf0e10cSrcweir     void * pAddr = rtl_cache_alloc (m_entry_cache);
203cdf0e10cSrcweir     if (pAddr != 0)
204cdf0e10cSrcweir     {
205cdf0e10cSrcweir         // construct.
206cdf0e10cSrcweir         return new(pAddr) Entry (rxPage, nOffset);
207cdf0e10cSrcweir     }
208cdf0e10cSrcweir     return 0;
209cdf0e10cSrcweir }
210cdf0e10cSrcweir 
destroy(Entry * entry)211cdf0e10cSrcweir void EntryCache::destroy (Entry * entry)
212cdf0e10cSrcweir {
213cdf0e10cSrcweir     if (entry != 0)
214cdf0e10cSrcweir     {
215cdf0e10cSrcweir         // destruct.
216cdf0e10cSrcweir         entry->~Entry();
217cdf0e10cSrcweir 
218cdf0e10cSrcweir         // return to cache.
219cdf0e10cSrcweir         rtl_cache_free (m_entry_cache, entry);
220cdf0e10cSrcweir     }
221cdf0e10cSrcweir }
222cdf0e10cSrcweir 
223cdf0e10cSrcweir /*========================================================================
224cdf0e10cSrcweir  *
225cdf0e10cSrcweir  * highbit():= log2() + 1 (complexity O(1))
226cdf0e10cSrcweir  *
227cdf0e10cSrcweir  *======================================================================*/
highbit(sal_Size n)228cdf0e10cSrcweir static int highbit(sal_Size n)
229cdf0e10cSrcweir {
230*c1e8cc3aSDon Lewis     int k = 1;
231cdf0e10cSrcweir 
232cdf0e10cSrcweir     if (n == 0)
233cdf0e10cSrcweir         return (0);
234cdf0e10cSrcweir #if SAL_TYPES_SIZEOFLONG == 8
235cdf0e10cSrcweir     if (n & 0xffffffff00000000ul)
236cdf0e10cSrcweir         k |= 32, n >>= 32;
237cdf0e10cSrcweir #endif
238cdf0e10cSrcweir     if (n & 0xffff0000)
239cdf0e10cSrcweir         k |= 16, n >>= 16;
240cdf0e10cSrcweir     if (n & 0xff00)
241cdf0e10cSrcweir         k |= 8, n >>= 8;
242cdf0e10cSrcweir     if (n & 0xf0)
243cdf0e10cSrcweir         k |= 4, n >>= 4;
244cdf0e10cSrcweir     if (n & 0x0c)
245cdf0e10cSrcweir         k |= 2, n >>= 2;
246cdf0e10cSrcweir     if (n & 0x02)
247cdf0e10cSrcweir         k++;
248cdf0e10cSrcweir 
249cdf0e10cSrcweir     return (k);
250cdf0e10cSrcweir }
251cdf0e10cSrcweir 
252cdf0e10cSrcweir /*========================================================================
253cdf0e10cSrcweir  *
254cdf0e10cSrcweir  * PageCache_Impl implementation.
255cdf0e10cSrcweir  *
256cdf0e10cSrcweir  *======================================================================*/
257cdf0e10cSrcweir namespace store
258cdf0e10cSrcweir {
259cdf0e10cSrcweir 
260cdf0e10cSrcweir class PageCache_Impl :
261cdf0e10cSrcweir     public store::OStoreObject,
262cdf0e10cSrcweir     public store::PageCache
263cdf0e10cSrcweir {
264cdf0e10cSrcweir     /** Representation.
265cdf0e10cSrcweir      */
266cdf0e10cSrcweir     static size_t const theTableSize = 32;
267cdf0e10cSrcweir     STORE_STATIC_ASSERT(STORE_IMPL_ISP2(theTableSize));
268cdf0e10cSrcweir 
269cdf0e10cSrcweir     Entry **     m_hash_table;
270cdf0e10cSrcweir     Entry *      m_hash_table_0[theTableSize];
271cdf0e10cSrcweir     size_t       m_hash_size;
272cdf0e10cSrcweir     size_t       m_hash_shift;
273cdf0e10cSrcweir     size_t const m_page_shift;
274cdf0e10cSrcweir 
275cdf0e10cSrcweir     size_t       m_hash_entries; // total number of entries in table.
276cdf0e10cSrcweir     size_t       m_nHit;
277cdf0e10cSrcweir     size_t       m_nMissed;
278cdf0e10cSrcweir 
hash_Impl(sal_uInt32 a,size_t s,size_t q,size_t m)279cdf0e10cSrcweir     inline int hash_Impl(sal_uInt32 a, size_t s, size_t q, size_t m)
280cdf0e10cSrcweir     {
281cdf0e10cSrcweir         return ((((a) + ((a) >> (s)) + ((a) >> ((s) << 1))) >> (q)) & (m));
282cdf0e10cSrcweir     }
hash_index_Impl(sal_uInt32 nOffset)283cdf0e10cSrcweir     inline int hash_index_Impl (sal_uInt32 nOffset)
284cdf0e10cSrcweir     {
285cdf0e10cSrcweir         return hash_Impl(nOffset, m_hash_shift, m_page_shift, m_hash_size - 1);
286cdf0e10cSrcweir     }
287cdf0e10cSrcweir 
288cdf0e10cSrcweir     Entry * lookup_Impl (Entry * entry, sal_uInt32 nOffset);
289cdf0e10cSrcweir     void rescale_Impl (sal_Size new_size);
290cdf0e10cSrcweir 
291cdf0e10cSrcweir     /** PageCache Implementation.
292cdf0e10cSrcweir      */
293cdf0e10cSrcweir     virtual storeError lookupPageAt_Impl (
294cdf0e10cSrcweir         PageHolder & rxPage,
295cdf0e10cSrcweir         sal_uInt32   nOffset);
296cdf0e10cSrcweir 
297cdf0e10cSrcweir     virtual storeError insertPageAt_Impl (
298cdf0e10cSrcweir         PageHolder const & rxPage,
299cdf0e10cSrcweir         sal_uInt32         nOffset);
300cdf0e10cSrcweir 
301cdf0e10cSrcweir     virtual storeError updatePageAt_Impl (
302cdf0e10cSrcweir         PageHolder const & rxPage,
303cdf0e10cSrcweir         sal_uInt32         nOffset);
304cdf0e10cSrcweir 
305cdf0e10cSrcweir     virtual storeError removePageAt_Impl (
306cdf0e10cSrcweir         sal_uInt32 nOffset);
307cdf0e10cSrcweir 
308cdf0e10cSrcweir     /** Not implemented.
309cdf0e10cSrcweir      */
310cdf0e10cSrcweir     PageCache_Impl (PageCache_Impl const &);
311cdf0e10cSrcweir     PageCache_Impl & operator= (PageCache_Impl const &);
312cdf0e10cSrcweir 
313cdf0e10cSrcweir public:
314cdf0e10cSrcweir     /** Construction.
315cdf0e10cSrcweir      */
316cdf0e10cSrcweir     explicit PageCache_Impl (sal_uInt16 nPageSize);
317cdf0e10cSrcweir 
318cdf0e10cSrcweir     /** Delegate multiple inherited IReference.
319cdf0e10cSrcweir      */
320cdf0e10cSrcweir     virtual oslInterlockedCount SAL_CALL acquire();
321cdf0e10cSrcweir     virtual oslInterlockedCount SAL_CALL release();
322cdf0e10cSrcweir 
323cdf0e10cSrcweir protected:
324cdf0e10cSrcweir     /** Destruction.
325cdf0e10cSrcweir      */
326cdf0e10cSrcweir     virtual ~PageCache_Impl (void);
327cdf0e10cSrcweir };
328cdf0e10cSrcweir 
329cdf0e10cSrcweir } // namespace store
330cdf0e10cSrcweir 
PageCache_Impl(sal_uInt16 nPageSize)331cdf0e10cSrcweir PageCache_Impl::PageCache_Impl (sal_uInt16 nPageSize)
332cdf0e10cSrcweir     : m_hash_table   (m_hash_table_0),
333cdf0e10cSrcweir       m_hash_size    (theTableSize),
334cdf0e10cSrcweir       m_hash_shift   (highbit(m_hash_size) - 1),
335cdf0e10cSrcweir       m_page_shift   (highbit(nPageSize) - 1),
336cdf0e10cSrcweir       m_hash_entries (0),
337cdf0e10cSrcweir       m_nHit         (0),
338cdf0e10cSrcweir       m_nMissed      (0)
339cdf0e10cSrcweir {
340cdf0e10cSrcweir     static size_t const theSize = sizeof(m_hash_table_0) / sizeof(m_hash_table_0[0]);
341cdf0e10cSrcweir     STORE_STATIC_ASSERT(theSize == theTableSize);
342cdf0e10cSrcweir     memset(m_hash_table_0, 0, sizeof(m_hash_table_0));
343cdf0e10cSrcweir }
344cdf0e10cSrcweir 
~PageCache_Impl()345cdf0e10cSrcweir PageCache_Impl::~PageCache_Impl()
346cdf0e10cSrcweir {
347cdf0e10cSrcweir     double s_x = 0.0, s_xx = 0.0;
348cdf0e10cSrcweir     sal_Size i, n = m_hash_size;
349cdf0e10cSrcweir     for (i = 0; i < n; i++)
350cdf0e10cSrcweir     {
351cdf0e10cSrcweir         int x = 0;
352cdf0e10cSrcweir         Entry * entry = m_hash_table[i];
353cdf0e10cSrcweir         while (entry != 0)
354cdf0e10cSrcweir         {
355cdf0e10cSrcweir             m_hash_table[i] = entry->m_pNext, entry->m_pNext = 0;
356cdf0e10cSrcweir             EntryCache::get().destroy (entry);
357cdf0e10cSrcweir             entry = m_hash_table[i];
358cdf0e10cSrcweir             x += 1;
359cdf0e10cSrcweir         }
360cdf0e10cSrcweir         s_x  += double(x);
361cdf0e10cSrcweir         s_xx += double(x) * double(x);
362cdf0e10cSrcweir     }
363cdf0e10cSrcweir     double ave = s_x / double(n);
364cdf0e10cSrcweir     OSL_TRACE("ave hash chain length: %g", ave);
365cdf0e10cSrcweir     (void) ave;
366cdf0e10cSrcweir 
367cdf0e10cSrcweir     if (m_hash_table != m_hash_table_0)
368cdf0e10cSrcweir     {
369cdf0e10cSrcweir         rtl_freeMemory (m_hash_table);
370cdf0e10cSrcweir         m_hash_table = m_hash_table_0;
371cdf0e10cSrcweir         m_hash_size  = theTableSize;
372cdf0e10cSrcweir         m_hash_shift = highbit(m_hash_size) - 1;
373cdf0e10cSrcweir     }
374cdf0e10cSrcweir     OSL_TRACE("Hits: %u, Misses: %u", m_nHit, m_nMissed);
375cdf0e10cSrcweir }
376cdf0e10cSrcweir 
acquire()377cdf0e10cSrcweir oslInterlockedCount PageCache_Impl::acquire()
378cdf0e10cSrcweir {
379cdf0e10cSrcweir     return OStoreObject::acquire();
380cdf0e10cSrcweir }
381cdf0e10cSrcweir 
release()382cdf0e10cSrcweir oslInterlockedCount PageCache_Impl::release()
383cdf0e10cSrcweir {
384cdf0e10cSrcweir     return OStoreObject::release();
385cdf0e10cSrcweir }
386cdf0e10cSrcweir 
rescale_Impl(sal_Size new_size)387cdf0e10cSrcweir void PageCache_Impl::rescale_Impl (sal_Size new_size)
388cdf0e10cSrcweir {
389cdf0e10cSrcweir     sal_Size new_bytes = new_size * sizeof(Entry*);
390cdf0e10cSrcweir     Entry ** new_table = (Entry**)(rtl_allocateMemory(new_bytes));
391cdf0e10cSrcweir 
392cdf0e10cSrcweir     if (new_table != 0)
393cdf0e10cSrcweir     {
394cdf0e10cSrcweir         Entry ** old_table = m_hash_table;
395cdf0e10cSrcweir         sal_Size old_size  = m_hash_size;
396cdf0e10cSrcweir 
397cdf0e10cSrcweir         OSL_TRACE("ave chain length: %u, total entries: %u [old_size: %u, new_size: %u]",
398cdf0e10cSrcweir                   m_hash_entries >> m_hash_shift, m_hash_entries, old_size, new_size);
399cdf0e10cSrcweir 
400cdf0e10cSrcweir         memset (new_table, 0, new_bytes);
401cdf0e10cSrcweir 
402cdf0e10cSrcweir         m_hash_table = new_table;
403cdf0e10cSrcweir         m_hash_size  = new_size;
404cdf0e10cSrcweir         m_hash_shift = highbit(m_hash_size) - 1;
405cdf0e10cSrcweir 
406cdf0e10cSrcweir         sal_Size i;
407cdf0e10cSrcweir         for (i = 0; i < old_size; i++)
408cdf0e10cSrcweir         {
409cdf0e10cSrcweir             Entry * curr = old_table[i];
410cdf0e10cSrcweir             while (curr != 0)
411cdf0e10cSrcweir             {
412cdf0e10cSrcweir                 Entry * next = curr->m_pNext;
413cdf0e10cSrcweir                 int index = hash_index_Impl(curr->m_nOffset);
414cdf0e10cSrcweir                 curr->m_pNext = m_hash_table[index], m_hash_table[index] = curr;
415cdf0e10cSrcweir                 curr = next;
416cdf0e10cSrcweir             }
417cdf0e10cSrcweir             old_table[i] = 0;
418cdf0e10cSrcweir         }
419cdf0e10cSrcweir         if (old_table != m_hash_table_0)
420cdf0e10cSrcweir         {
421cdf0e10cSrcweir             //
422cdf0e10cSrcweir             rtl_freeMemory (old_table);
423cdf0e10cSrcweir         }
424cdf0e10cSrcweir     }
425cdf0e10cSrcweir }
426cdf0e10cSrcweir 
lookup_Impl(Entry * entry,sal_uInt32 nOffset)427cdf0e10cSrcweir Entry * PageCache_Impl::lookup_Impl (Entry * entry, sal_uInt32 nOffset)
428cdf0e10cSrcweir {
429*c1e8cc3aSDon Lewis     int lookups = 0;
430cdf0e10cSrcweir     while (entry != 0)
431cdf0e10cSrcweir     {
432cdf0e10cSrcweir         if (entry->m_nOffset == nOffset)
433cdf0e10cSrcweir             break;
434cdf0e10cSrcweir 
435cdf0e10cSrcweir         lookups += 1;
436cdf0e10cSrcweir         entry = entry->m_pNext;
437cdf0e10cSrcweir     }
438cdf0e10cSrcweir     if (lookups > 2)
439cdf0e10cSrcweir     {
440cdf0e10cSrcweir         sal_Size new_size = m_hash_size, ave = m_hash_entries >> m_hash_shift;
441cdf0e10cSrcweir         for (; ave > 4; new_size *= 2, ave /= 2)
442cdf0e10cSrcweir             continue;
443cdf0e10cSrcweir         if (new_size != m_hash_size)
444cdf0e10cSrcweir             rescale_Impl (new_size);
445cdf0e10cSrcweir     }
446cdf0e10cSrcweir     return entry;
447cdf0e10cSrcweir }
448cdf0e10cSrcweir 
lookupPageAt_Impl(PageHolder & rxPage,sal_uInt32 nOffset)449cdf0e10cSrcweir storeError PageCache_Impl::lookupPageAt_Impl (
450cdf0e10cSrcweir     PageHolder & rxPage,
451cdf0e10cSrcweir     sal_uInt32   nOffset)
452cdf0e10cSrcweir {
453cdf0e10cSrcweir     int index = hash_index_Impl(nOffset);
454cdf0e10cSrcweir     Entry const * entry = lookup_Impl (m_hash_table[index], nOffset);
455cdf0e10cSrcweir     if (entry != 0)
456cdf0e10cSrcweir     {
457cdf0e10cSrcweir         // Existing entry.
458cdf0e10cSrcweir         rxPage = entry->m_xPage;
459cdf0e10cSrcweir 
460cdf0e10cSrcweir         // Update stats and leave.
461cdf0e10cSrcweir         m_nHit += 1;
462cdf0e10cSrcweir         return store_E_None;
463cdf0e10cSrcweir     }
464cdf0e10cSrcweir 
465cdf0e10cSrcweir     // Cache miss. Update stats and leave.
466cdf0e10cSrcweir     m_nMissed += 1;
467cdf0e10cSrcweir     return store_E_NotExists;
468cdf0e10cSrcweir }
469cdf0e10cSrcweir 
insertPageAt_Impl(PageHolder const & rxPage,sal_uInt32 nOffset)470cdf0e10cSrcweir storeError PageCache_Impl::insertPageAt_Impl (
471cdf0e10cSrcweir     PageHolder const & rxPage,
472cdf0e10cSrcweir     sal_uInt32         nOffset)
473cdf0e10cSrcweir {
474cdf0e10cSrcweir     Entry * entry = EntryCache::get().create (rxPage, nOffset);
475cdf0e10cSrcweir     if (entry != 0)
476cdf0e10cSrcweir     {
477cdf0e10cSrcweir         // Insert new entry.
478cdf0e10cSrcweir         int index = hash_index_Impl(nOffset);
479cdf0e10cSrcweir         entry->m_pNext = m_hash_table[index], m_hash_table[index] = entry;
480cdf0e10cSrcweir 
481cdf0e10cSrcweir         // Update stats and leave.
482cdf0e10cSrcweir         m_hash_entries += 1;
483cdf0e10cSrcweir         return store_E_None;
484cdf0e10cSrcweir     }
485cdf0e10cSrcweir     return store_E_OutOfMemory;
486cdf0e10cSrcweir }
487cdf0e10cSrcweir 
updatePageAt_Impl(PageHolder const & rxPage,sal_uInt32 nOffset)488cdf0e10cSrcweir storeError PageCache_Impl::updatePageAt_Impl (
489cdf0e10cSrcweir     PageHolder const & rxPage,
490cdf0e10cSrcweir     sal_uInt32         nOffset)
491cdf0e10cSrcweir {
492cdf0e10cSrcweir     int index = hash_index_Impl(nOffset);
493cdf0e10cSrcweir     Entry *  entry  = lookup_Impl (m_hash_table[index], nOffset);
494cdf0e10cSrcweir     if (entry != 0)
495cdf0e10cSrcweir     {
496cdf0e10cSrcweir         // Update existing entry.
497cdf0e10cSrcweir         entry->m_xPage = rxPage;
498cdf0e10cSrcweir 
499cdf0e10cSrcweir         // Update stats and leave. // m_nUpdHit += 1;
500cdf0e10cSrcweir         return store_E_None;
501cdf0e10cSrcweir     }
502cdf0e10cSrcweir     return insertPageAt_Impl (rxPage, nOffset);
503cdf0e10cSrcweir }
504cdf0e10cSrcweir 
removePageAt_Impl(sal_uInt32 nOffset)505cdf0e10cSrcweir storeError PageCache_Impl::removePageAt_Impl (
506cdf0e10cSrcweir     sal_uInt32 nOffset)
507cdf0e10cSrcweir {
508cdf0e10cSrcweir     Entry ** ppEntry = &(m_hash_table[hash_index_Impl(nOffset)]);
509cdf0e10cSrcweir     while (*ppEntry != 0)
510cdf0e10cSrcweir     {
511cdf0e10cSrcweir         if ((*ppEntry)->m_nOffset == nOffset)
512cdf0e10cSrcweir         {
513cdf0e10cSrcweir             // Existing entry.
514cdf0e10cSrcweir             Entry * entry = (*ppEntry);
515cdf0e10cSrcweir 
516cdf0e10cSrcweir             // Dequeue and destroy entry.
517cdf0e10cSrcweir             (*ppEntry) = entry->m_pNext, entry->m_pNext = 0;
518cdf0e10cSrcweir             EntryCache::get().destroy (entry);
519cdf0e10cSrcweir 
520cdf0e10cSrcweir             // Update stats and leave.
521cdf0e10cSrcweir             m_hash_entries -= 1;
522cdf0e10cSrcweir             return store_E_None;
523cdf0e10cSrcweir         }
524cdf0e10cSrcweir         ppEntry = &((*ppEntry)->m_pNext);
525cdf0e10cSrcweir     }
526cdf0e10cSrcweir     return store_E_NotExists;
527cdf0e10cSrcweir }
528cdf0e10cSrcweir 
529cdf0e10cSrcweir /*========================================================================
530cdf0e10cSrcweir  *
531cdf0e10cSrcweir  * Old OStorePageCache implementation.
532cdf0e10cSrcweir  *
533cdf0e10cSrcweir  * (two-way association (sorted address array, LRU chain)).
534cdf0e10cSrcweir  * (external OStorePageData representation).
535cdf0e10cSrcweir  *
536cdf0e10cSrcweir  *======================================================================*/
537cdf0e10cSrcweir 
538cdf0e10cSrcweir /*========================================================================
539cdf0e10cSrcweir  *
540cdf0e10cSrcweir  * PageCache factory implementation.
541cdf0e10cSrcweir  *
542cdf0e10cSrcweir  *======================================================================*/
543cdf0e10cSrcweir namespace store {
544cdf0e10cSrcweir 
545cdf0e10cSrcweir storeError
PageCache_createInstance(rtl::Reference<store::PageCache> & rxCache,sal_uInt16 nPageSize)546cdf0e10cSrcweir PageCache_createInstance (
547cdf0e10cSrcweir     rtl::Reference< store::PageCache > & rxCache,
548cdf0e10cSrcweir     sal_uInt16                           nPageSize)
549cdf0e10cSrcweir {
550cdf0e10cSrcweir     rxCache = new PageCache_Impl (nPageSize);
551cdf0e10cSrcweir     if (!rxCache.is())
552cdf0e10cSrcweir         return store_E_OutOfMemory;
553cdf0e10cSrcweir 
554cdf0e10cSrcweir     return store_E_None;
555cdf0e10cSrcweir }
556cdf0e10cSrcweir 
557cdf0e10cSrcweir } // namespace store
558