4 #include "utils/array.h"
5 #include "utils/memutils.h"
8 * Deconstructed array cache
11 typedef struct ArrayCacheEntry {
17 struct ArrayCacheEntry *prev;
18 struct ArrayCacheEntry *next;
23 typedef struct ArrayCache {
26 ArrayCacheEntry *head;
27 ArrayCacheEntry *tail;
28 ArrayCacheEntry* entries[ NENTRIES ];
33 moveFirst(ArrayCache *ac, ArrayCacheEntry *entry)
36 * delete entry form a list
38 Assert( entry != ac->head );
39 if ( entry == ac->tail )
41 Assert( entry->next == NULL );
42 ac->tail = entry->prev;
44 ac->tail->next = NULL;
50 entry->prev->next = entry->next;
51 entry->next->prev = entry->prev;
58 Assert( ac->head != NULL );
59 Assert( ac->tail != NULL );
61 entry->next = ac->head;
63 ac->head->prev = entry;
67 #define DATUMSIZE(d) VARSIZE_ANY(DatumGetPointer(d))
69 cmpDatum(Datum a, Datum b)
71 int32 la = DATUMSIZE(a);
72 int32 lb = DATUMSIZE(b);
75 return memcmp( DatumGetPointer(a), DatumGetPointer(b), la );
77 return (la > lb) ? 1 : -1;
81 fetchData(ArrayCache *ac, ArrayCacheEntry *entry, ArrayType **da, SimpleArray **sa, struct SmlSign **ss )
85 info = findProcs( ARR_ELEMTYPE(entry->da) );
89 if ( entry->sa == NULL )
95 old = MemoryContextSwitchTo( ac->ctx );
96 entry->sa = Array2SimpleArrayU(info, entry->da, (getSmlType() == ST_TFIDF) ? ac : NULL);
97 MemoryContextSwitchTo(old);
105 if ( entry->ss == NULL )
109 getFmgrInfoHash(info);
111 old = MemoryContextSwitchTo( ac->ctx );
112 entry->ss = Array2HashedArray(info, entry->da);
113 MemoryContextSwitchTo(old);
124 cleanupData(ArrayCacheEntry *entry)
128 if ( entry->sa->elems )
129 pfree( entry->sa->elems );
131 pfree( entry->sa->df );
132 if ( entry->sa->hash )
133 pfree( entry->sa->hash );
142 pfree( DatumGetPointer(entry->toastedArray) );
147 makeEntry(ArrayCache *ac, ArrayCacheEntry *entry, Datum a)
149 ArrayType *detoastedArray;
151 entry->toastedArray = (Datum)MemoryContextAlloc( ac->ctx, DATUMSIZE(a) );
152 memcpy( DatumGetPointer(entry->toastedArray), DatumGetPointer(a), DATUMSIZE(a) );
154 detoastedArray = (ArrayType*)PG_DETOAST_DATUM(entry->toastedArray);
155 entry->da = MemoryContextAlloc( ac->ctx, VARSIZE(detoastedArray));
156 memcpy( entry->da, detoastedArray, VARSIZE(detoastedArray));
160 cmpEntry(const void *a, const void *b)
162 return cmpDatum( (*(ArrayCacheEntry**)a)->toastedArray, (*(ArrayCacheEntry**)b)->toastedArray );
166 SearchArrayCache( void *cache, MemoryContext ctx, Datum a, ArrayType **da, SimpleArray **sa, struct SmlSign **ss )
169 ArrayCacheEntry *entry;
172 cache = MemoryContextAllocZero(ctx, sizeof(ArrayCache));
174 ac = (ArrayCache*) cache;
178 * Fast check of resent used value
180 if ( ac->head && cmpDatum(ac->head->toastedArray, a) == 0 )
182 fetchData(ac, ac->head, da, sa, ss);
186 if ( ac->head == NULL )
188 ac->entries[0] = ac->head = ac->tail = MemoryContextAllocZero(ctx, sizeof(ArrayCacheEntry));
190 makeEntry(ac, ac->head, a);
191 fetchData(ac, ac->head, da, sa, ss);
196 ArrayCacheEntry **StopLow = ac->entries;
197 ArrayCacheEntry **StopHigh = ac->entries + ac->nentries;
198 ArrayCacheEntry **StopMiddle;
201 while (StopLow < StopHigh) {
202 StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
204 cmp = cmpDatum(entry->toastedArray, a);
208 moveFirst(ac, entry);
209 fetchData(ac, ac->head, da, sa, ss);
213 StopLow = StopMiddle + 1;
215 StopHigh = StopMiddle;
223 if ( ac->nentries < NENTRIES )
225 entry = ac->entries[ ac->nentries ] = MemoryContextAllocZero(ctx, sizeof(ArrayCacheEntry));
228 entry->next = ac->head;
230 ac->head->prev = entry;
235 makeEntry(ac, ac->head, a);
236 fetchData(ac, ac->head, da, sa, ss);
240 cleanupData( ac->tail );
241 moveFirst(ac, ac->tail );
242 makeEntry(ac, ac->head, a);
243 fetchData(ac, ac->head, da, sa, ss);
246 qsort(ac->entries, ac->nentries, sizeof(ArrayCacheEntry*), cmpEntry);
251 fingArrayStat(void *cache, Oid typoid, Datum query, StatElem *low)
258 ac = (ArrayCache*) cache;
259 if ( ac->DocStat == NULL )
261 ac->DocStat = initStatCache(ac->ctx);
265 if ( typoid != ac->DocStat->info->typid )
266 elog(ERROR,"Types of stat table and actual arguments are different");
268 return findStat(ac->DocStat, query, low);
272 getStat(void *cache, size_t n)
279 ac = (ArrayCache*) cache;
280 if ( ac->DocStat == NULL )
281 ac->DocStat = initStatCache(ac->ctx);
283 getHashStatCache(ac->DocStat, ac->ctx, n);
289 allocateHash(void *cache, SimpleArray *a)
295 ac = (ArrayCache*) cache;
300 a->hash = MemoryContextAlloc( ac->ctx, sizeof(uint32) * a->nelems );