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-2016, 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
52 												 * heap scans */
53 	bool		cc_isname[CATCACHE_MAXKEYS];	/* flag "name" key columns */
54 	dlist_head	cc_lists;		/* list of CatCList structs */
55 #ifdef CATCACHE_STATS
56 	long		cc_searches;	/* total # searches against this cache */
57 	long		cc_hits;		/* # of matches against existing entry */
58 	long		cc_neg_hits;	/* # of matches against negative entry */
59 	long		cc_newloads;	/* # of successful loads of new entry */
60 
61 	/*
62 	 * cc_searches - (cc_hits + cc_neg_hits + cc_newloads) is number of failed
63 	 * searches, each of which will result in loading a negative entry
64 	 */
65 	long		cc_invals;		/* # of entries invalidated from cache */
66 	long		cc_lsearches;	/* total # list-searches */
67 	long		cc_lhits;		/* # of matches against existing lists */
68 #endif
69 	dlist_head *cc_bucket;		/* hash buckets */
70 } CatCache;
71 
72 
73 typedef struct catctup
74 {
75 	int			ct_magic;		/* for identifying CatCTup entries */
76 #define CT_MAGIC   0x57261502
77 	CatCache   *my_cache;		/* link to owning catcache */
78 
79 	/*
80 	 * Each tuple in a cache is a member of a dlist that stores the elements
81 	 * of its hash bucket.  We keep each dlist in LRU order to speed repeated
82 	 * lookups.
83 	 */
84 	dlist_node	cache_elem;		/* list member of per-bucket list */
85 
86 	/*
87 	 * The tuple may also be a member of at most one CatCList.  (If a single
88 	 * catcache is list-searched with varying numbers of keys, we may have to
89 	 * make multiple entries for the same tuple because of this restriction.
90 	 * Currently, that's not expected to be common, so we accept the potential
91 	 * inefficiency.)
92 	 */
93 	struct catclist *c_list;	/* containing CatCList, or NULL if none */
94 
95 	/*
96 	 * A tuple marked "dead" must not be returned by subsequent searches.
97 	 * However, it won't be physically deleted from the cache until its
98 	 * refcount goes to zero.  (If it's a member of a CatCList, the list's
99 	 * refcount must go to zero, too; also, remember to mark the list dead at
100 	 * the same time the tuple is marked.)
101 	 *
102 	 * A negative cache entry is an assertion that there is no tuple matching
103 	 * a particular key.  This is just as useful as a normal entry so far as
104 	 * avoiding catalog searches is concerned.  Management of positive and
105 	 * negative entries is identical.
106 	 */
107 	int			refcount;		/* number of active references */
108 	bool		dead;			/* dead but not yet removed? */
109 	bool		negative;		/* negative cache entry? */
110 	uint32		hash_value;		/* hash value for this tuple's keys */
111 	HeapTupleData tuple;		/* tuple management header */
112 } CatCTup;
113 
114 
115 typedef struct catclist
116 {
117 	int			cl_magic;		/* for identifying CatCList entries */
118 #define CL_MAGIC   0x52765103
119 	CatCache   *my_cache;		/* link to owning catcache */
120 
121 	/*
122 	 * A CatCList describes the result of a partial search, ie, a search using
123 	 * only the first K key columns of an N-key cache.  We form the keys used
124 	 * into a tuple (with other attributes NULL) to represent the stored key
125 	 * set.  The CatCList object contains links to cache entries for all the
126 	 * table rows satisfying the partial key.  (Note: none of these will be
127 	 * negative cache entries.)
128 	 *
129 	 * A CatCList is only a member of a per-cache list; we do not currently
130 	 * divide them into hash buckets.
131 	 *
132 	 * A list marked "dead" must not be returned by subsequent searches.
133 	 * However, it won't be physically deleted from the cache until its
134 	 * refcount goes to zero.  (A list should be marked dead if any of its
135 	 * member entries are dead.)
136 	 *
137 	 * If "ordered" is true then the member tuples appear in the order of the
138 	 * cache's underlying index.  This will be true in normal operation, but
139 	 * might not be true during bootstrap or recovery operations. (namespace.c
140 	 * is able to save some cycles when it is true.)
141 	 */
142 	dlist_node	cache_elem;		/* list member of per-catcache list */
143 	int			refcount;		/* number of active references */
144 	bool		dead;			/* dead but not yet removed? */
145 	bool		ordered;		/* members listed in index order? */
146 	short		nkeys;			/* number of lookup keys specified */
147 	uint32		hash_value;		/* hash value for lookup keys */
148 	HeapTupleData tuple;		/* header for tuple holding keys */
149 	int			n_members;		/* number of member tuples */
150 	CatCTup    *members[FLEXIBLE_ARRAY_MEMBER]; /* members */
151 } CatCList;
152 
153 
154 typedef struct catcacheheader
155 {
156 	slist_head	ch_caches;		/* head of list of CatCache structs */
157 	int			ch_ntup;		/* # of tuples in all caches */
158 } CatCacheHeader;
159 
160 
161 /* this extern duplicates utils/memutils.h... */
162 extern PGDLLIMPORT MemoryContext CacheMemoryContext;
163 
164 extern void CreateCacheMemoryContext(void);
165 
166 extern CatCache *InitCatCache(int id, Oid reloid, Oid indexoid,
167 			 int nkeys, const int *key,
168 			 int nbuckets);
169 extern void InitCatCachePhase2(CatCache *cache, bool touch_index);
170 
171 extern HeapTuple SearchCatCache(CatCache *cache,
172 			   Datum v1, Datum v2,
173 			   Datum v3, Datum v4);
174 extern void ReleaseCatCache(HeapTuple tuple);
175 
176 extern uint32 GetCatCacheHashValue(CatCache *cache,
177 					 Datum v1, Datum v2,
178 					 Datum v3, Datum v4);
179 
180 extern CatCList *SearchCatCacheList(CatCache *cache, int nkeys,
181 				   Datum v1, Datum v2,
182 				   Datum v3, Datum v4);
183 extern void ReleaseCatCacheList(CatCList *list);
184 
185 extern void ResetCatalogCaches(void);
186 extern void CatalogCacheFlushCatalog(Oid catId);
187 extern void CatCacheInvalidate(CatCache *cache, uint32 hashValue);
188 extern void PrepareToInvalidateCacheTuple(Relation relation,
189 							  HeapTuple tuple,
190 							  HeapTuple newtuple,
191 							  void (*function) (int, uint32, Oid));
192 
193 extern void PrintCatCacheLeakWarning(HeapTuple tuple);
194 extern void PrintCatCacheListLeakWarning(CatCList *list);
195 
196 #endif   /* CATCACHE_H */
197