/* * sepgsql_subxact_callback * * A callback routine of sub-transaction start/abort/commit. Releases all * security labels that are set within the sub-transaction that is aborted. */ static void sepgsql_subxact_callback(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg) { ListCell *cell; ListCell *prev; ListCell *next; if (event == SUBXACT_EVENT_ABORT_SUB) { prev = NULL; for (cell = list_head(client_label_pending); cell; cell = next) { pending_label *plabel = lfirst(cell); next = lnext(cell); if (plabel->subid == mySubid) client_label_pending = list_delete_cell(client_label_pending, cell, prev); else prev = cell; } } }
/* * Delete the first element of the list. * * This is useful to replace the Lisp-y code "list = lnext(list);" in cases * where the intent is to alter the list rather than just traverse it. * Beware that the removed cell is freed, whereas the lnext() coding leaves * the original list head intact if there's another pointer to it. */ List * list_delete_first(List *list) { if (list == NIL) return NIL; /* would an error be better? */ return list_delete_cell(list, list_head(list), NULL); }
/* * Delete the first element of the list. * * This is useful to replace the Lisp-y code "list = lnext(list);" in cases * where the intent is to alter the list rather than just traverse it. * Beware that the removed cell is freed, whereas the lnext() coding leaves * the original list head intact if there's another pointer to it. */ List * list_delete_first(List *list) { check_list_invariants(list); if (list == NIL) return NIL; /* would an error be better? */ return list_delete_cell(list, list_head(list), NULL); }
/* As above, but use simple pointer equality */ List * list_delete_ptr(List *list, void *datum) { ListCell *cell; ListCell *prev; Assert(IsPointerList(list)); prev = NULL; foreach(cell, list) { if (lfirst(cell) == datum) return list_delete_cell(list, cell, prev); prev = cell; } /* Didn't find a match: return the list unmodified */ return list; }
/* As above, but for OIDs */ List * list_delete_oid(List *list, Oid datum) { ListCell *cell; ListCell *prev; Assert(IsOidList(list)); check_list_invariants(list); prev = NULL; foreach(cell, list) { if (lfirst_oid(cell) == datum) return list_delete_cell(list, cell, prev); prev = cell; } /* Didn't find a match: return the list unmodified */ return list; }
/* * Delete the first cell in list that matches datum, if any. * Equality is determined via equal(). */ List * list_delete(List *list, void *datum) { ListCell *cell; ListCell *prev; Assert(IsPointerList(list)); check_list_invariants(list); prev = NULL; foreach(cell, list) { if (equal(lfirst(cell), datum)) return list_delete_cell(list, cell, prev); prev = cell; } /* Didn't find a match: return the list unmodified */ return list; }
/* * Reclaim caches recently unreferenced */ static void sepgsql_avc_reclaim(void) { ListCell *cell; ListCell *next; ListCell *prev; int index; while (avc_num_caches >= avc_threshold - AVC_NUM_RECLAIM) { index = avc_lru_hint; prev = NULL; for (cell = list_head(avc_slots[index]); cell; cell = next) { avc_cache *cache = lfirst(cell); next = lnext(cell); if (!cache->hot_cache) { avc_slots[index] = list_delete_cell(avc_slots[index], cell, prev); pfree(cache->scontext); pfree(cache->tcontext); if (cache->ncontext) pfree(cache->ncontext); pfree(cache); avc_num_caches--; } else { cache->hot_cache = false; prev = cell; } } avc_lru_hint = (avc_lru_hint + 1) % AVC_NUM_SLOTS; } }
/* * StandbyReleaseLocksMany * Release standby locks held by XIDs < removeXid * * If keepPreparedXacts is true, keep prepared transactions even if * they're older than removeXid */ static void StandbyReleaseLocksMany(TransactionId removeXid, bool keepPreparedXacts) { ListCell *cell, *prev, *next; LOCKTAG locktag; /* * Release all matching locks. */ prev = NULL; for (cell = list_head(RecoveryLockList); cell; cell = next) { xl_standby_lock *lock = (xl_standby_lock *) lfirst(cell); next = lnext(cell); if (!TransactionIdIsValid(removeXid) || TransactionIdPrecedes(lock->xid, removeXid)) { if (keepPreparedXacts && StandbyTransactionIdIsPrepared(lock->xid)) continue; elog(trace_recovery(DEBUG4), "releasing recovery lock: xid %u db %u rel %u", lock->xid, lock->dbOid, lock->relOid); SET_LOCKTAG_RELATION(locktag, lock->dbOid, lock->relOid); if (!LockRelease(&locktag, AccessExclusiveLock, true)) elog(LOG, "RecoveryLockList contains entry for lock no longer recorded by lock manager: xid %u database %u relation %u", lock->xid, lock->dbOid, lock->relOid); RecoveryLockList = list_delete_cell(RecoveryLockList, cell, prev); pfree(lock); } else prev = cell; } }
static void StandbyReleaseLocks(TransactionId xid) { ListCell *cell, *prev, *next; /* * Release all matching locks and remove them from list */ prev = NULL; for (cell = list_head(RecoveryLockList); cell; cell = next) { xl_standby_lock *lock = (xl_standby_lock *) lfirst(cell); next = lnext(cell); if (!TransactionIdIsValid(xid) || lock->xid == xid) { LOCKTAG locktag; elog(trace_recovery(DEBUG4), "releasing recovery lock: xid %u db %u rel %u", lock->xid, lock->dbOid, lock->relOid); SET_LOCKTAG_RELATION(locktag, lock->dbOid, lock->relOid); if (!LockRelease(&locktag, AccessExclusiveLock, true)) elog(LOG, "RecoveryLockList contains entry for lock no longer recorded by lock manager: xid %u database %u relation %u", lock->xid, lock->dbOid, lock->relOid); RecoveryLockList = list_delete_cell(RecoveryLockList, cell, prev); pfree(lock); } else prev = cell; } }