StreamBatch *StreamBatchCreate(Bitmapset *readers, int num_tuples) { char *ptr = ShmemDynAlloc0(sizeof(StreamBatch) + BITMAPSET_SIZE(readers->nwords) + (bms_num_members(readers) * sizeof(int))); StreamBatch *batch = (StreamBatch *) ptr; int cq_id; int i = 0; batch->id = rand() ^ (int) MyProcPid; batch->num_tups = num_tuples; batch->num_wtups = bms_num_members(readers) * num_tuples; SpinLockInit(&batch->mutex); ptr += sizeof(StreamBatch); batch->readers = (Bitmapset *) ptr; memcpy(batch->readers, readers, BITMAPSET_SIZE(readers->nwords)); ptr += BITMAPSET_SIZE(readers->nwords); batch->proc_runs = (int *) ptr; readers = bms_copy(readers); while ((cq_id = bms_first_member(readers)) != -1) { CQProcEntry *pentry = GetCQProcEntry(cq_id); batch->proc_runs[i] = Max(pentry->proc_runs, pentry->pg_size); i++; } pfree(readers); return batch; }
/* * _outBitmapset - * converts a bitmap set of integers * * Note: the output format is "(b int int ...)", similar to an integer List. */ void _outBitmapset(StringInfo str, const Bitmapset *bms) { Bitmapset *tmpset; int x; appendStringInfoChar(str, '('); appendStringInfoChar(str, 'b'); tmpset = bms_copy(bms); while ((x = bms_first_member(tmpset)) >= 0) appendStringInfo(str, " %d", x); bms_free(tmpset); appendStringInfoChar(str, ')'); }
/* * fixup_inherited_columns * * When user is querying on a table with children, it implicitly accesses * child tables also. So, we also need to check security label of child * tables and columns, but here is no guarantee attribute numbers are * same between the parent ans children. * It returns a bitmapset which contains attribute number of the child * table based on the given bitmapset of the parent. */ static Bitmapset * fixup_inherited_columns(Oid parentId, Oid childId, Bitmapset *columns) { AttrNumber attno; Bitmapset *tmpset; Bitmapset *result = NULL; char *attname; int index; /* * obviously, no need to do anything here */ if (parentId == childId) return columns; tmpset = bms_copy(columns); while ((index = bms_first_member(tmpset)) > 0) { attno = index + FirstLowInvalidHeapAttributeNumber; /* * whole-row-reference shall be fixed-up later */ if (attno == InvalidAttrNumber) { result = bms_add_member(result, index); continue; } attname = get_attname(parentId, attno); if (!attname) elog(ERROR, "cache lookup failed for attribute %d of relation %u", attno, parentId); attno = get_attnum(childId, attname); if (attno == InvalidAttrNumber) elog(ERROR, "cache lookup failed for attribute %s of relation %u", attname, childId); index = attno - FirstLowInvalidHeapAttributeNumber; result = bms_add_member(result, index); pfree(attname); } bms_free(tmpset); return result; }
/* * GetAnyDataNode * Pick any data node from given set, but try a preferred node */ int GetAnyDataNode(Bitmapset *nodes) { Bitmapset *preferred = NULL; int i, nodeid; int nmembers = 0; int members[NumDataNodes]; for (i = 0; i < num_preferred_data_nodes; i++) { char ntype = PGXC_NODE_DATANODE; nodeid = PGXCNodeGetNodeId(preferred_data_node[i], &ntype); /* OK, found one */ if (bms_is_member(nodeid, nodes)) preferred = bms_add_member(preferred, nodeid); } /* * If no preferred data nodes or they are not in the desired set, pick up * from the original set. */ if (bms_is_empty(preferred)) preferred = bms_copy(nodes); /* * Load balance. * We can not get item from the set, convert it to array */ while ((nodeid = bms_first_member(preferred)) >= 0) members[nmembers++] = nodeid; bms_free(preferred); /* If there is a single member nothing to balance */ if (nmembers == 1) return members[0]; /* * In general, the set may contain any number of nodes, and if we save * previous returned index for load balancing the distribution won't be * flat, because small set will probably reset saved value, and lower * indexes will be picked up more often. * So we just get a random value from 0..nmembers-1. */ return members[((unsigned int) random()) % nmembers]; }
static int num_cq_crashes(StreamBatch *batch) { int cq_id; int num_crashes = 0; Bitmapset *readers = bms_copy(batch->readers); int i = 0; while ((cq_id = bms_first_member(readers)) != -1) { CQProcEntry *pentry = GetCQProcEntry(cq_id); if (!pentry) num_crashes++; else if (batch->proc_runs[i] < pentry->proc_runs) num_crashes++; i++; } pfree(readers); return num_crashes; }
/* * check_relation_privileges * * It actually checks required permissions on a certain relation * and its columns. */ static bool check_relation_privileges(Oid relOid, Bitmapset *selected, Bitmapset *inserted, Bitmapset *updated, uint32 required, bool abort_on_violation) { ObjectAddress object; char *audit_name; Bitmapset *columns; int index; char relkind = get_rel_relkind(relOid); bool result = true; /* * Hardwired Policies: SE-PostgreSQL enforces - clients cannot modify * system catalogs using DMLs - clients cannot reference/modify toast * relations using DMLs */ if (sepgsql_getenforce() > 0) { Oid relnamespace = get_rel_namespace(relOid); if (IsSystemNamespace(relnamespace) && (required & (SEPG_DB_TABLE__UPDATE | SEPG_DB_TABLE__INSERT | SEPG_DB_TABLE__DELETE)) != 0) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("SELinux: hardwired security policy violation"))); if (relkind == RELKIND_TOASTVALUE) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("SELinux: hardwired security policy violation"))); } /* * Check permissions on the relation */ object.classId = RelationRelationId; object.objectId = relOid; object.objectSubId = 0; audit_name = getObjectIdentity(&object); switch (relkind) { case RELKIND_RELATION: case RELKIND_PARTITIONED_TABLE: result = sepgsql_avc_check_perms(&object, SEPG_CLASS_DB_TABLE, required, audit_name, abort_on_violation); break; case RELKIND_SEQUENCE: Assert((required & ~SEPG_DB_TABLE__SELECT) == 0); if (required & SEPG_DB_TABLE__SELECT) result = sepgsql_avc_check_perms(&object, SEPG_CLASS_DB_SEQUENCE, SEPG_DB_SEQUENCE__GET_VALUE, audit_name, abort_on_violation); break; case RELKIND_VIEW: result = sepgsql_avc_check_perms(&object, SEPG_CLASS_DB_VIEW, SEPG_DB_VIEW__EXPAND, audit_name, abort_on_violation); break; default: /* nothing to be checked */ break; } pfree(audit_name); /* * Only columns owned by relations shall be checked */ if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE) return true; /* * Check permissions on the columns */ selected = fixup_whole_row_references(relOid, selected); inserted = fixup_whole_row_references(relOid, inserted); updated = fixup_whole_row_references(relOid, updated); columns = bms_union(selected, bms_union(inserted, updated)); while ((index = bms_first_member(columns)) >= 0) { AttrNumber attnum; uint32 column_perms = 0; if (bms_is_member(index, selected)) column_perms |= SEPG_DB_COLUMN__SELECT; if (bms_is_member(index, inserted)) { if (required & SEPG_DB_TABLE__INSERT) column_perms |= SEPG_DB_COLUMN__INSERT; } if (bms_is_member(index, updated)) { if (required & SEPG_DB_TABLE__UPDATE) column_perms |= SEPG_DB_COLUMN__UPDATE; } if (column_perms == 0) continue; /* obtain column's permission */ attnum = index + FirstLowInvalidHeapAttributeNumber; object.classId = RelationRelationId; object.objectId = relOid; object.objectSubId = attnum; audit_name = getObjectDescription(&object); result = sepgsql_avc_check_perms(&object, SEPG_CLASS_DB_COLUMN, column_perms, audit_name, abort_on_violation); pfree(audit_name); if (!result) return result; } return true; }