9
9
*
10
10
*
11
11
* IDENTIFICATION
12
- * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.95 2006/04/01 03:03:36 tgl Exp $
12
+ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.96 2006/04/25 22:46:05 tgl Exp $
13
13
*
14
14
* NOTES
15
15
* Postgres btree pages look like ordinary relation pages. The opaque
26
26
#include "miscadmin.h"
27
27
#include "storage/freespace.h"
28
28
#include "storage/lmgr.h"
29
+ #include "utils/inval.h"
29
30
30
31
31
32
/*
@@ -99,6 +100,49 @@ _bt_getroot(Relation rel, int access)
99
100
uint32 rootlevel ;
100
101
BTMetaPageData * metad ;
101
102
103
+ /*
104
+ * Try to use previously-cached metapage data to find the root. This
105
+ * normally saves one buffer access per index search, which is a very
106
+ * helpful savings in bufmgr traffic and hence contention.
107
+ */
108
+ if (rel -> rd_amcache != NULL )
109
+ {
110
+ metad = (BTMetaPageData * ) rel -> rd_amcache ;
111
+ /* We shouldn't have cached it if any of these fail */
112
+ Assert (metad -> btm_magic == BTREE_MAGIC );
113
+ Assert (metad -> btm_version == BTREE_VERSION );
114
+ Assert (metad -> btm_root != P_NONE );
115
+
116
+ rootblkno = metad -> btm_fastroot ;
117
+ Assert (rootblkno != P_NONE );
118
+ rootlevel = metad -> btm_fastlevel ;
119
+
120
+ rootbuf = _bt_getbuf (rel , rootblkno , BT_READ );
121
+ rootpage = BufferGetPage (rootbuf );
122
+ rootopaque = (BTPageOpaque ) PageGetSpecialPointer (rootpage );
123
+
124
+ /*
125
+ * Since the cache might be stale, we check the page more carefully
126
+ * here than normal. We *must* check that it's not deleted.
127
+ * If it's not alone on its level, then we reject too --- this
128
+ * may be overly paranoid but better safe than sorry. Note we
129
+ * don't check P_ISROOT, because that's not set in a "fast root".
130
+ */
131
+ if (!P_IGNORE (rootopaque ) &&
132
+ rootopaque -> btpo .level == rootlevel &&
133
+ P_LEFTMOST (rootopaque ) &&
134
+ P_RIGHTMOST (rootopaque ))
135
+ {
136
+ /* OK, accept cached page as the root */
137
+ return rootbuf ;
138
+ }
139
+ _bt_relbuf (rel , rootbuf );
140
+ /* Cache is stale, throw it away */
141
+ if (rel -> rd_amcache )
142
+ pfree (rel -> rd_amcache );
143
+ rel -> rd_amcache = NULL ;
144
+ }
145
+
102
146
metabuf = _bt_getbuf (rel , BTREE_METAPAGE , BT_READ );
103
147
metapg = BufferGetPage (metabuf );
104
148
metaopaque = (BTPageOpaque ) PageGetSpecialPointer (metapg );
@@ -200,6 +244,12 @@ _bt_getroot(Relation rel, int access)
200
244
201
245
END_CRIT_SECTION ();
202
246
247
+ /*
248
+ * Send out relcache inval for metapage change (probably unnecessary
249
+ * here, but let's be safe).
250
+ */
251
+ CacheInvalidateRelcache (rel );
252
+
203
253
/*
204
254
* swap root write lock for read lock. There is no danger of anyone
205
255
* else accessing the new root page while it's unlocked, since no one
@@ -217,6 +267,13 @@ _bt_getroot(Relation rel, int access)
217
267
Assert (rootblkno != P_NONE );
218
268
rootlevel = metad -> btm_fastlevel ;
219
269
270
+ /*
271
+ * Cache the metapage data for next time
272
+ */
273
+ rel -> rd_amcache = MemoryContextAlloc (rel -> rd_indexcxt ,
274
+ sizeof (BTMetaPageData ));
275
+ memcpy (rel -> rd_amcache , metad , sizeof (BTMetaPageData ));
276
+
220
277
/*
221
278
* We are done with the metapage; arrange to release it via first
222
279
* _bt_relandgetbuf call
@@ -280,6 +337,16 @@ _bt_gettrueroot(Relation rel)
280
337
uint32 rootlevel ;
281
338
BTMetaPageData * metad ;
282
339
340
+ /*
341
+ * We don't try to use cached metapage data here, since (a) this path is
342
+ * not performance-critical, and (b) if we are here it suggests our cache
343
+ * is out-of-date anyway. In light of point (b), it's probably safest to
344
+ * actively flush any cached metapage info.
345
+ */
346
+ if (rel -> rd_amcache )
347
+ pfree (rel -> rd_amcache );
348
+ rel -> rd_amcache = NULL ;
349
+
283
350
metabuf = _bt_getbuf (rel , BTREE_METAPAGE , BT_READ );
284
351
metapg = BufferGetPage (metabuf );
285
352
metaopaque = (BTPageOpaque ) PageGetSpecialPointer (metapg );
@@ -1052,9 +1119,12 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
1052
1119
1053
1120
END_CRIT_SECTION ();
1054
1121
1055
- /* release buffers */
1122
+ /* release buffers; send out relcache inval if metapage changed */
1056
1123
if (BufferIsValid (metabuf ))
1124
+ {
1125
+ CacheInvalidateRelcache (rel );
1057
1126
_bt_relbuf (rel , metabuf );
1127
+ }
1058
1128
_bt_relbuf (rel , pbuf );
1059
1129
_bt_relbuf (rel , rbuf );
1060
1130
_bt_relbuf (rel , buf );
0 commit comments