1 /*-------------------------------------------------------------------------
2  *
3  * catcache.h
4  *	  Low-level catalog cache definitions.
5  *
6  * NOTE: every catalog cache must have a corresponding unique index on
7  * the system table that it caches --- ie, the index must match the keys
8  * used to do lookups in this cache.  All cache fetches are done with
9  * indexscans (under normal conditions).  The index should be unique to
10  * guarantee that there can only be one matching row for a key combination.
11  *
12  *
13  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
14  * Portions Copyright (c) 1994, Regents of the University of California
15  *
16  * src/include/utils/catcache.h
17  *
18  *-------------------------------------------------------------------------
19  */
20 #ifndef CATCACHE_H
21 #define CATCACHE_H
22 
23 #include "access/htup.h"
24 #include "access/skey.h"
25 #include "lib/ilist.h"
26 #include "utils/relcache.h"
27 
28 /*
29  *		struct catctup:			individual tuple in the cache.
30  *		struct catclist:		list of tuples matching a partial key.
31  *		struct catcache:		information for managing a cache.
32  *		struct catcacheheader:	information for managing all the caches.
33  */
34 
35 #define CATCACHE_MAXKEYS		4
36 
37 typedef struct catcache
38 {
39 	int			id;				/* cache identifier --- see syscache.h */
40 	slist_node	cc_next;		/* list link */
41 	const char *cc_relname;		/* name of relation the tuples come from */
42 	Oid			cc_reloid;		/* OID of relation the tuples come from */
43 	Oid			cc_indexoid;	/* OID of index matching cache keys */
44 	bool		cc_relisshared; /* is relation shared across databases? */
45 	TupleDesc	cc_tupdesc;		/* tuple descriptor (copied from reldesc) */
46 	int			cc_ntup;		/* # of tuples currently in this cache */
47 	int			cc_nbuckets;	/* # of hash buckets in this cache */
48 	int			cc_nkeys;		/* # of keys (1..CATCACHE_MAXKEYS) */
49 	int			cc_key[CATCACHE_MAXKEYS];	/* AttrNumber of each key */
50 	PGFunction	cc_hashfunc[CATCACHE_MAXKEYS];	/* hash function for each key */
51 	ScanKeyData cc_skey[CATCACHE_MAXKEYS];	/* precomputed key info for heap
52 											 * scans */
53 	bool		cc_isname[CATCACHE_MAXKEYS];	/* flag "name" key columns */
54 	dlist_head	cc_lists;		/* list of CatCList structs */
55 	dlist_head *cc_bucket;		/* hash buckets */
56 
57 	/*
58 	 * Keep these at the end, so that compiling catcache.c with CATCACHE_STATS
59 	 * doesn't break ABI for other modules
60 	 */
61 #ifdef CATCACHE_STATS
62 	long		cc_searches;	/* total # searches against this cache */
63 	long		cc_hits;		/* # of matches against existing entry */
64 	long		cc_neg_hits;	/* # of matches against negative entry */
65 	long		cc_newloads;	/* # of successful loads of new entry */
66 
67 	/*
68 	 * cc_searches - (cc_hits + cc_neg_hits + cc_newloads) is number of failed
69 	 * searches, each of which will result in loading a negative entry
70 	 */
71 	long		cc_invals;		/* # of entries invalidated from cache */
72 	long		cc_lsearches;	/* total # list-searches */
73 	long		cc_lhits;		/* # of matches against existing lists */
74 #endif
75 } CatCache;
76 
77 
78 typedef struct catctup
79 {
80 	int			ct_magic;		/* for identifying CatCTup entries */
81 #define CT_MAGIC   0x57261502
82 	CatCache   *my_cache;		/* link to owning catcache */
83 
84 	/*
85 	 * Each tuple in a cache is a member of a dlist that stores the elements
86 	 * of its hash bucket.  We keep each dlist in LRU order to speed repeated
87 	 * lookups.
88 	 */
89 	dlist_node	cache_elem;		/* list member of per-bucket list */
90 
91 	/*
92 	 * The tuple may also be a member of at most one CatCList.  (If a single
93 	 * catcache is list-searched with varying numbers of keys, we may have to
94 	 * make multiple entries for the same tuple because of this restriction.
95 	 * Currently, that's not expected to be common, so we accept the potential
96 	 * inefficiency.)
97 	 */
98 	struct catclist *c_list;	/* containing CatCList, or NULL if none */
99 
100 	/*
101 	 * A tuple marked "dead" must not be returned by subsequent searches.
102 	 * However, it won't be physically deleted from the cache until its
103 	 * refcount goes to zero.  (If it's a member of a CatCList, the list's
104 	 * refcount must go to zero, too; also, remember to mark the list dead at
105 	 * the same time the tuple is marked.)
106 	 *
107 	 * A negative cache entry is an assertion that there is no tuple matching
108 	 * a particular key.  This is just as useful as a normal entry so far as
109 	 * avoiding catalog searches is concerned.  Management of positive and
110 	 * negative entries is identical.
111 	 */
112 	int			refcount;		/* number of active references */
113 	bool		dead;			/* dead but not yet removed? */
114 	bool		negative;		/* negative cache entry? */
115 	uint32		hash_value;		/* hash value for this tuple's keys */
116 	HeapTupleData tuple;		/* tuple management header */
117 } CatCTup;
118 
119 
120 typedef struct catclist
121 {
122 	int			cl_magic;		/* for identifying CatCList entries */
123 #define CL_MAGIC   0x52765103
124 	CatCache   *my_cache;		/* link to owning catcache */
125 
126 	/*
127 	 * A CatCList describes the result of a partial search, ie, a search using
128 	 * only the first K key columns of an N-key cache.  We form the keys used
129 	 * into a tuple (with other attributes NULL) to represent the stored key
130 	 * set.  The CatCList object contains links to cache entries for all the
131 	 * table rows satisfying the partial key.  (Note: none of these will be
132 	 * negative cache entries.)
133 	 *
134 	 * A CatCList is only a member of a per-cache list; we do not currently
135 	 * divide them into hash buckets.
136 	 *
137 	 * A list marked "dead" must not be returned by subsequent searches.
138 	 * However, it won't be physically deleted from the cache until its
139 	 * refcount goes to zero.  (A list should be marked dead if any of its
140 	 * member entries are dead.)
141 	 *
142 	 * If "ordered" is true then the member tuples appear in the order of the
143 	 * cache's underlying index.  This will be true in normal operation, but
144 	 * might not be true during bootstrap or recovery operations. (namespace.c
145 	 * is able to save some cycles when it is true.)
146 	 */
147 	dlist_node	cache_elem;		/* list member of per-catcache list */
148 	int			refcount;		/* number of active references */
149 	bool		dead;			/* dead but not yet removed? */
150 	bool		ordered;		/* members listed in index order? */
151 	short		nkeys;			/* number of lookup keys specified */
152 	uint32		hash_value;		/* hash value for lookup keys */
153 	HeapTupleData tuple;		/* header for tuple holding keys */
154 	int			n_members;		/* number of member tuples */
155 	CatCTup    *members[FLEXIBLE_ARRAY_MEMBER]; /* members */
156 } CatCList;
157 
158 
159 typedef struct catcacheheader
160 {
161 	slist_head	ch_caches;		/* head of list of CatCache structs */
162 	int			ch_ntup;		/* # of tuples in all caches */
163 } CatCacheHeader;
164 
165 
166 /* this extern duplicates utils/memutils.h... */
167 extern PGDLLIMPORT MemoryContext CacheMemoryContext;
168 
169 extern void CreateCacheMemoryContext(void);
170 
171 extern CatCache *InitCatCache(int id, Oid reloid, Oid indexoid,
172 			 int nkeys, const int *key,
173 			 int nbuckets);
174 extern void InitCatCachePhase2(CatCache *cache, bool touch_index);
175 
176 extern HeapTuple SearchCatCache(CatCache *cache,
177 			   Datum v1, Datum v2,
178 			   Datum v3, Datum v4);
179 extern void ReleaseCatCache(HeapTuple tuple);
180 
181 extern uint32 GetCatCacheHashValue(CatCache *cache,
182 					 Datum v1, Datum v2,
183 					 Datum v3, Datum v4);
184 
185 extern CatCList *SearchCatCacheList(CatCache *cache, int nkeys,
186 				   Datum v1, Datum v2,
187 				   Datum v3, Datum v4);
188 extern void ReleaseCatCacheList(CatCList *list);
189 
190 extern void ResetCatalogCaches(void);
191 extern void CatalogCacheFlushCatalog(Oid catId);
192 extern void CatCacheInvalidate(CatCache *cache, uint32 hashValue);
193 extern void PrepareToInvalidateCacheTuple(Relation relation,
194 							  HeapTuple tuple,
195 							  HeapTuple newtuple,
196 							  void (*function) (int, uint32, Oid));
197 
198 extern void PrintCatCacheLeakWarning(HeapTuple tuple);
199 extern void PrintCatCacheListLeakWarning(CatCList *list);
200 
201 #endif							/* CATCACHE_H */
202