* BufferAlloc -- subroutine for ReadBuffer. Handles lookup of a shared * buffer. If no buffer exists already, selects a replacement * victim and evicts the old page, but does NOT read in new page. * * "strategy" can be a buffer replacement strategy object, or NULL for * the default strategy. The selected buffer's usage_count is advanced when * using the default strategy, but otherwise p
| 1212 | * No locks are held either at entry or exit. |
| 1213 | */ |
| 1214 | static BufferDesc * |
| 1215 | BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum, |
| 1216 | BlockNumber blockNum, |
| 1217 | BufferAccessStrategy strategy, |
| 1218 | bool *foundPtr) |
| 1219 | { |
| 1220 | BufferTag newTag; /* identity of requested block */ |
| 1221 | uint32 newHash; /* hash value for newTag */ |
| 1222 | LWLock *newPartitionLock; /* buffer partition lock for it */ |
| 1223 | BufferTag oldTag; /* previous identity of selected buffer */ |
| 1224 | uint32 oldHash; /* hash value for oldTag */ |
| 1225 | LWLock *oldPartitionLock; /* buffer partition lock for it */ |
| 1226 | uint32 oldFlags; |
| 1227 | int buf_id; |
| 1228 | BufferDesc *buf; |
| 1229 | bool valid; |
| 1230 | uint32 buf_state; |
| 1231 | |
| 1232 | /* create a tag so we can lookup the buffer */ |
| 1233 | INIT_BUFFERTAG(newTag, smgr->smgr_rnode.node, forkNum, blockNum); |
| 1234 | |
| 1235 | /* determine its hash code and partition lock ID */ |
| 1236 | newHash = BufTableHashCode(&newTag); |
| 1237 | newPartitionLock = BufMappingPartitionLock(newHash); |
| 1238 | |
| 1239 | /* see if the block is in the buffer pool already */ |
| 1240 | LWLockAcquire(newPartitionLock, LW_SHARED); |
| 1241 | buf_id = BufTableLookup(&newTag, newHash); |
| 1242 | if (buf_id >= 0) |
| 1243 | { |
| 1244 | /* |
| 1245 | * Found it. Now, pin the buffer so no one can steal it from the |
| 1246 | * buffer pool, and check to see if the correct data has been loaded |
| 1247 | * into the buffer. |
| 1248 | */ |
| 1249 | buf = GetBufferDescriptor(buf_id); |
| 1250 | |
| 1251 | valid = PinBuffer(buf, strategy); |
| 1252 | |
| 1253 | /* Can release the mapping lock as soon as we've pinned it */ |
| 1254 | LWLockRelease(newPartitionLock); |
| 1255 | |
| 1256 | *foundPtr = true; |
| 1257 | |
| 1258 | if (!valid) |
| 1259 | { |
| 1260 | /* |
| 1261 | * We can only get here if (a) someone else is still reading in |
| 1262 | * the page, or (b) a previous read attempt failed. We have to |
| 1263 | * wait for any active read attempt to finish, and then set up our |
| 1264 | * own read attempt if the page is still not BM_VALID. |
| 1265 | * StartBufferIO does it all. |
| 1266 | */ |
| 1267 | if (StartBufferIO(buf, true)) |
| 1268 | { |
| 1269 | /* |
| 1270 | * If we get here, previous attempts to read the buffer must |
| 1271 | * have failed ... but we shall bravely try again. |
no test coverage detected