Exemplo n.º 1
0
Arquivo: outfast.c Projeto: huor/gpdb
static void
_outList(StringInfo str, List *node)
{
	ListCell   *lc;

	if (node == NULL)
	{
		int16 tg = 0;
		appendBinaryStringInfo(str, (const char *)&tg, sizeof(int16));
		return;
	}

	WRITE_NODE_TYPE("");
    WRITE_INT_FIELD(length);

	foreach(lc, node)
	{

		if (IsA(node, List))
		{
			_outNode(str, lfirst(lc));
		}
		else if (IsA(node, IntList))
		{
			int n = lfirst_int(lc);
			appendBinaryStringInfo(str, (const char *)&n, sizeof(int));
		}
		else if (IsA(node, OidList))
		{
			Oid n = lfirst_oid(lc);
			appendBinaryStringInfo(str, (const char *)&n, sizeof(Oid));
		}
	}
}
Exemplo n.º 2
0
/*
 * get_next_id
 *
 * Gets the smallest possible id to assign to the next continuous view.
 * We keep this minimal so that we can minimize the size of bitmaps used
 * to tag stream buffer events with.
 */
static int32
get_next_id(Relation rel)
{
	HeapScanDesc	scandesc;
	HeapTuple		tup;
	int32			id = 1;
	List			*idsList = NIL;
	ListCell		*lc;

	scandesc = heap_beginscan_catalog(rel, 0, NULL);

	while ((tup = heap_getnext(scandesc, ForwardScanDirection)) != NULL)
	{
		Form_pipeline_query row = (Form_pipeline_query) GETSTRUCT(tup);
		idsList = lappend_int(idsList, row->id);
	}

	heap_endscan(scandesc);

	if (idsList != NIL)
	{
		int32 ids[idsList->length];
		int i = 0;
		foreach(lc, idsList)
		{
			ids[i] = lfirst_int(lc);
			i++;
		}
Exemplo n.º 3
0
/*
 * Reads the GP catalog tables and build a CdbComponentDatabases structure.
 * It then converts this to a Gang structure and initializes all the non-connection related fields.
 *
 * Call this function in GangContext.
 * Returns a not-null pointer.
 */
Gang *
buildGangDefinition(List *segments, SegmentType segmentType)
{
	Gang *newGangDefinition = NULL;
	ListCell *lc;
	int	i = 0;
	int	size;
	int contentId;

	size = list_length(segments);

	ELOG_DISPATCHER_DEBUG("buildGangDefinition:Starting %d qExec processes for gang", size);

	Assert(CurrentMemoryContext == DispatcherContext);

	/* allocate a gang */
	newGangDefinition = (Gang *) palloc0(sizeof(Gang));
	newGangDefinition->type = GANGTYPE_UNALLOCATED;
	newGangDefinition->size = size;
	newGangDefinition->allocated = false;
	newGangDefinition->db_descriptors =
		(SegmentDatabaseDescriptor **) palloc0(size * sizeof(SegmentDatabaseDescriptor*));

	PG_TRY();
	{
		/* initialize db_descriptors */
		foreach_with_count (lc, segments , i)
		{
			contentId = lfirst_int(lc);
			newGangDefinition->db_descriptors[i] =
						cdbcomponent_allocateIdleQE(contentId, segmentType);
		}
	}
Exemplo n.º 4
0
/*
 * GetPreferredReplicationNode
 * Pick any Datanode from given list, however fetch a preferred node first.
 */
List *
GetPreferredReplicationNode(List *relNodes)
{
	/*
	 * Try to find the first node in given list relNodes
	 * that is in the list of preferred nodes
	 */
	if (num_preferred_data_nodes != 0)
	{
		ListCell	*item;
		foreach(item, relNodes)
		{
			int		relation_nodeid = lfirst_int(item);
			int		i;
			for (i = 0; i < num_preferred_data_nodes; i++)
			{
#ifdef XCP
				char nodetype = PGXC_NODE_DATANODE;
				int nodeid = PGXCNodeGetNodeId(preferred_data_node[i],
											   &nodetype);
#else
				int nodeid = PGXCNodeGetNodeId(preferred_data_node[i], PGXC_NODE_DATANODE);
#endif

				/* OK, found one */
				if (nodeid == relation_nodeid)
					return lappend_int(NULL, nodeid);
			}
		}
Exemplo n.º 5
0
void
tf_write_one_row(StringInfo msgbuf,
			  FmgrInfo *out_funcs,
			  List *attnumlist,
			  Datum *values,
			  bool *nulls)
{
	ListCell   *cur;
	char	   *string;

	bool need_delim = false;

	foreach(cur, attnumlist)
	{
		int			attnum = lfirst_int(cur);
		Datum		value = values[attnum - 1];
		bool		isnull = nulls[attnum - 1];

		if (need_delim)
			tf_write_char(msgbuf, '\t');

		need_delim = true;

		if (isnull)
		{
			tf_write_string(msgbuf, "\\N");
		}
		else
		{
			string = OutputFunctionCall(&out_funcs[attnum - 1],
										value);

			tf_write_attribute_out_text(msgbuf,'\t',string);
		}
	}
Exemplo n.º 6
0
static void add_projection_desc_httpheader(CHURL_HEADERS headers, ProjectionInfo *projInfo, List *qualsAttributes) {
    int i;
    char long_number[sizeof(int32) * 8];
    int *varNumbers = projInfo->pi_varNumbers;
    StringInfoData formatter;
    initStringInfo(&formatter);

    /* Convert the number of projection columns to a string */
    pg_ltoa(list_length(projInfo->pi_targetlist) + list_length(qualsAttributes), long_number);
    churl_headers_append(headers, "X-GP-ATTRS-PROJ", long_number);

    for(i = 0; i < list_length(projInfo->pi_targetlist); i++) {
        int number = varNumbers[i] - 1;
        pg_ltoa(number, long_number);
        resetStringInfo(&formatter);
        appendStringInfo(&formatter, "X-GP-ATTRS-PROJ-IDX");

        churl_headers_append(headers, formatter.data,long_number);
    }

	ListCell *attribute = NULL;

	foreach(attribute, qualsAttributes)
	{
		AttrNumber attrNumber = lfirst_int(attribute);

		pg_ltoa(attrNumber, long_number);
		resetStringInfo(&formatter);
		appendStringInfo(&formatter, "X-GP-ATTRS-PROJ-IDX");

		churl_headers_append(headers, formatter.data,long_number);
	}
Exemplo n.º 7
0
/*
 * This function extracts the command type and id of the modified relation from a
 * a PlannedStmt. This is done in preparation to call auto_stats()
 */
void
autostats_get_cmdtype(QueryDesc *queryDesc, AutoStatsCmdType * pcmdType, Oid *prelationOid)
{
	PlannedStmt *stmt = queryDesc->plannedstmt;
	Oid			relationOid = InvalidOid;		/* relation that is modified */
	AutoStatsCmdType cmdType = AUTOSTATS_CMDTYPE_SENTINEL;		/* command type */
	RangeTblEntry *rte = NULL;

	switch (stmt->commandType)
	{
		case CMD_SELECT:
			if (stmt->intoClause != NULL)
			{
				/* CTAS */
				if (queryDesc->estate->es_into_relation_descriptor)
					relationOid = RelationGetRelid(queryDesc->estate->es_into_relation_descriptor);
				cmdType = AUTOSTATS_CMDTYPE_CTAS;
			}
			break;
		case CMD_INSERT:
			rte = rt_fetch(lfirst_int(list_head(stmt->resultRelations)), stmt->rtable);
			relationOid = rte->relid;
			cmdType = AUTOSTATS_CMDTYPE_INSERT;
			break;
		case CMD_UPDATE:
			rte = rt_fetch(lfirst_int(list_head(stmt->resultRelations)), stmt->rtable);
			relationOid = rte->relid;
			cmdType = AUTOSTATS_CMDTYPE_UPDATE;
			break;
		case CMD_DELETE:
			rte = rt_fetch(lfirst_int(list_head(stmt->resultRelations)), stmt->rtable);
			relationOid = rte->relid;
			cmdType = AUTOSTATS_CMDTYPE_DELETE;
			break;
		case CMD_UTILITY:
		case CMD_UNKNOWN:
		case CMD_NOTHING:
			break;
		default:
			Assert(false);
			break;
	}

	Assert(cmdType >= 0 && cmdType <= AUTOSTATS_CMDTYPE_SENTINEL);
	*pcmdType = cmdType;
	*prelationOid = relationOid;
}
Exemplo n.º 8
0
/*
 * This variant of list_concat_unique() operates upon lists of integers.
 */
List *
list_concat_unique_int(List *list1, List *list2)
{
	ListCell   *cell;

	Assert(IsIntegerList(list1));
	Assert(IsIntegerList(list2));

	foreach(cell, list2)
	{
		if (!list_member_int(list1, lfirst_int(cell)))
			list1 = lappend_int(list1, lfirst_int(cell));
	}

	check_list_invariants(list1);
	return list1;
}
Exemplo n.º 9
0
/*
 * find_all_inheritors -
 *		Returns a list of relation OIDs including the given rel plus
 *		all relations that inherit from it, directly or indirectly.
 *		Optionally, it also returns the number of parents found for
 *		each such relation within the inheritance tree rooted at the
 *		given rel.
 *
 * The specified lock type is acquired on all child relations (but not on the
 * given rel; caller should already have locked it).  If lockmode is NoLock
 * then no locks are acquired, but caller must beware of race conditions
 * against possible DROPs of child relations.
 */
List *
find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
{
	List	   *rels_list,
			   *rel_numparents;
	ListCell   *l;

	/*
	 * We build a list starting with the given rel and adding all direct and
	 * indirect children.  We can use a single list as both the record of
	 * already-found rels and the agenda of rels yet to be scanned for more
	 * children.  This is a bit tricky but works because the foreach() macro
	 * doesn't fetch the next list element until the bottom of the loop.
	 */
	rels_list = list_make1_oid(parentrelId);
	rel_numparents = list_make1_int(0);

	foreach(l, rels_list)
	{
		Oid			currentrel = lfirst_oid(l);
		List	   *currentchildren;
		ListCell   *lc;

		/* Get the direct children of this rel */
		currentchildren = find_inheritance_children(currentrel, lockmode);

		/*
		 * Add to the queue only those children not already seen. This avoids
		 * making duplicate entries in case of multiple inheritance paths from
		 * the same parent.  (It'll also keep us from getting into an infinite
		 * loop, though theoretically there can't be any cycles in the
		 * inheritance graph anyway.)
		 */
		foreach(lc, currentchildren)
		{
			Oid			child_oid = lfirst_oid(lc);
			bool		found = false;
			ListCell   *lo;
			ListCell   *li;

			/* if the rel is already there, bump number-of-parents counter */
			forboth(lo, rels_list, li, rel_numparents)
			{
				if (lfirst_oid(lo) == child_oid)
				{
					lfirst_int(li)++;
					found = true;
					break;
				}
			}

			/* if it's not there, add it. expect 1 parent, initially. */
			if (!found)
			{
				rels_list = lappend_oid(rels_list, child_oid);
				rel_numparents = lappend_int(rel_numparents, 1);
			}
		}
Exemplo n.º 10
0
/*
 * RemoteCopy_GetRelationLoc
 * Get relation node list based on COPY data involved. An empty list is
 * returned to caller if relation involved has no locator information
 * as it is the case of a system relation.
 */
void
RemoteCopy_GetRelationLoc(RemoteCopyData *state,
						  Relation rel,
                          List *attnums)
{
	ExecNodes  *exec_nodes = NULL;

	/*
	 * If target table does not exists on nodes (e.g. system table)
	 * the location info returned is NULL. This is the criteria, when
	 * we need to run COPY on Coordinator
	 */
	state->rel_loc = GetRelationLocInfo(RelationGetRelid(rel));

	if (state->rel_loc)
	{
		/*
		 * Pick up one node only
		 * This case corresponds to a replicated table with COPY TO
		 *
		 */
		exec_nodes = makeNode(ExecNodes);
		if (!state->is_from &&
			IsLocatorReplicated(state->rel_loc->locatorType))
			exec_nodes->nodeList = GetPreferredReplicationNode(state->rel_loc->nodeList);
		else
		{
			/* All nodes necessary */
			exec_nodes->nodeList = list_concat(exec_nodes->nodeList, state->rel_loc->nodeList);
		}
	}

	state->idx_dist_by_col = -1;
	if (state->rel_loc && state->rel_loc->partAttrNum != 0)
	{
		/*
		 * Find the column used as key for data distribution.
		 * First scan attributes of tuple descriptor with the list
		 * of attributes used in COPY if any list is specified.
		 * If no list is specified, set this value to the one of
		 * locator information.
		 */
		if (attnums != NIL)
		{
			ListCell   *cur;
			foreach(cur, attnums)
			{
				int attnum = lfirst_int(cur);

				if (state->rel_loc->partAttrNum == attnum)
				{
					state->idx_dist_by_col = attnum - 1;
					break;
				}
			}
		}
Exemplo n.º 11
0
/*
 * This variant of list_union() operates upon lists of integers.
 */
List *
list_union_int(const List *list1, const List *list2)
{
	List	   *result;
	const ListCell *cell;

	Assert(IsIntegerList(list1));
	Assert(IsIntegerList(list2));

	result = list_copy(list1);
	foreach(cell, list2)
	{
		if (!list_member_int(result, lfirst_int(cell)))
			result = lappend_int(result, lfirst_int(cell));
	}

	check_list_invariants(result);
	return result;
}
Exemplo n.º 12
0
ListCell *
lappend_cell_int(List *list, ListCell *prev, int datum)
{
	ListCell   *new_cell;

	Assert(IsIntegerList(list));

	new_cell = add_new_cell(list, prev);
	lfirst_int(new_cell) = datum;
	check_list_invariants(list);
	return new_cell;
}
Exemplo n.º 13
0
/*
 * This variant of list_difference() operates upon lists of integers.
 */
List *
list_difference_int(const List *list1, const List *list2)
{
	const ListCell *cell;
	List	   *result = NIL;

	Assert(IsIntegerList(list1));
	Assert(IsIntegerList(list2));

	if (list2 == NIL)
		return list_copy(list1);

	foreach(cell, list1)
	{
		if (!list_member_int(list2, lfirst_int(cell)))
			result = lappend_int(result, lfirst_int(cell));
	}

	check_list_invariants(result);
	return result;
}
Exemplo n.º 14
0
/*
 * As list_intersection but operates on lists of integers.
 */
List *
list_intersection_int(const List *list1, const List *list2)
{
	List	   *result;
	const ListCell *cell;

	if (list1 == NIL || list2 == NIL)
		return NIL;

	Assert(IsIntegerList(list1));
	Assert(IsIntegerList(list2));

	result = NIL;
	foreach(cell, list1)
	{
		if (list_member_int(list2, lfirst_int(cell)))
			result = lappend_int(result, lfirst_int(cell));
	}

	check_list_invariants(result);
	return result;
}
Exemplo n.º 15
0
/*
 *  Scan the (pre-parsed) hba file line by line, looking for a match
 *  to the port's connection request.
 */
static bool check_hba(POOL_CONNECTION *frontend)
{
	bool found_entry = false;
	bool error = false;
	ListCell *line;
	ListCell *line_num;

	forboth(line, hba_lines, line_num, hba_line_nums)
	{
		parse_hba(lfirst(line), lfirst_int(line_num),
				  frontend, &found_entry, &error);
		if (found_entry || error)
			break;
	}
Exemplo n.º 16
0
/*
 * Prepend an integer to the list. See lcons()
 */
List *
lcons_int(int datum, List *list)
{
	Assert(IsIntegerList(list));

	if (list == NIL)
		list = new_list(T_IntList);
	else
		new_head_cell(list);

	lfirst_int(list->head) = datum;
	check_list_invariants(list);
	return list;
}
Exemplo n.º 17
0
/*
 * Append an integer to the specified list. See lappend()
 */
List *
lappend_int(List *list, int datum)
{
	Assert(IsIntegerList(list));

	if (list == NIL)
		list = new_list(T_IntList);
	else
		new_tail_cell(list);

	lfirst_int(list->tail) = datum;
	check_list_invariants(list);
	return list;
}
Exemplo n.º 18
0
/* Use connection id. */
int useConnectionID(int32_t *connid)
{
	/* Ensure that we have potential enough connection IDs to utilize. */
	if ( PCONTRACK->FreeConnIDs == NULL )
	{
		*connid = INVALID_CONNID;
		return CONNTRACK_CONNID_FULL;
	}
	*connid = lfirst_int(list_head(PCONTRACK->FreeConnIDs));
	MEMORY_CONTEXT_SWITCH_TO(PCONTEXT)
	PCONTRACK->FreeConnIDs = list_delete_first(PCONTRACK->FreeConnIDs);
	MEMORY_CONTEXT_SWITCH_BACK
	elog(DEBUG3, "Resource manager uses connection track ID %d", *connid);
	return FUNC_RETURN_OK;
}
Exemplo n.º 19
0
/*
 * Return true iff the integer 'datum' is a member of the list.
 */
bool
list_member_int(const List *list, int datum)
{
	const ListCell *cell;

	Assert(IsIntegerList(list));
	check_list_invariants(list);

	foreach(cell, list)
	{
		if (lfirst_int(cell) == datum)
			return true;
	}

	return false;
}
Exemplo n.º 20
0
/* As above, but for integers */
List *
list_delete_int(List *list, int datum)
{
	ListCell   *cell;
	ListCell   *prev;

	Assert(IsIntegerList(list));
	check_list_invariants(list);

	prev = NULL;
	foreach(cell, list)
	{
		if (lfirst_int(cell) == datum)
			return list_delete_cell(list, cell, prev);

		prev = cell;
	}

	/* Didn't find a match: return the list unmodified */
	return list;
}
Exemplo n.º 21
0
/*
 * bms_overlap_list - does a set overlap an integer list?
 */
bool
bms_overlap_list(const Bitmapset *a, const List *b)
{
	ListCell   *lc;
	int			wordnum,
				bitnum;

	if (a == NULL || b == NIL)
		return false;

	foreach(lc, b)
	{
		int			x = lfirst_int(lc);

		if (x < 0)
			elog(ERROR, "negative bitmapset member not allowed");
		wordnum = WORDNUM(x);
		bitnum = BITNUM(x);
		if (wordnum < a->nwords)
			if ((a->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0)
				return true;
	}
Exemplo n.º 22
0
/*
 * GetAnyDataNode
 * Pick any Datanode from given list, but try a preferred node
 */
List *
GetAnyDataNode(List *relNodes)
{
    /*
     * Try to find the first node in given list relNodes
     * that is in the list of preferred nodes
     */
    if (num_preferred_data_nodes != 0)
    {
        ListCell	*item;
        foreach(item, relNodes)
        {
            int		relation_nodeid = lfirst_int(item);
            int		i;
            for (i = 0; i < num_preferred_data_nodes; i++)
            {
                int nodeid = PGXCNodeGetNodeId(preferred_data_node[i], PGXC_NODE_DATANODE);

                /* OK, found one */
                if (nodeid == relation_nodeid)
                    return lappend_int(NULL, nodeid);
            }
        }
Exemplo n.º 23
0
uint64 memReservedForParquetScan(Oid rel_oid, List* attr_list) {
	uint64		rowgroupsize = 0;
	char		*compresstype = NULL;
	uint64		memReserved = 0;

	int 		attrNum = get_relnatts(rel_oid); /*Get the total attribute number of the relation*/
	uint64		attsWidth = 0;		/*the sum width of attributes to be scanned*/
	uint64		recordWidth = 0;	/*the average width of one record in the relation*/
	/* The width array for all the attributes in the relation*/
	int32		*attWidth = (int32*)palloc0(attrNum * sizeof(int32));

	/** The variables for traversing through attribute list*/
	ListCell	*cell;

	/* Get rowgroup size and compress type */
	AppendOnlyEntry *aoEntry = GetAppendOnlyEntry(rel_oid, SnapshotNow);
	rowgroupsize = aoEntry->blocksize;
	compresstype = aoEntry->compresstype;


	/** For each column in the relation, get the column width
	 * 1) Get the column width from pg_attribute, estimate column width for to-be-scanned columns:
	 * If fixed column width, the attlen is the column width; if not fixed, refer to typmod
	 * 2) Get the average column width for variable length type column from table pg_statistic, if the
	 * stawidth not equals 0, set it as the column width.
	 */
	for(int i = 0; i < attrNum; i++){
		int att_id = i + 1;
		HeapTuple attTuple = caql_getfirst(NULL, cql("SELECT * FROM pg_attribute"
				" WHERE attrelid = :1 "
				" AND attnum = :2 ",
				ObjectIdGetDatum(rel_oid),
				Int16GetDatum(att_id)));

		if (HeapTupleIsValid(attTuple)) {
			/*Step1: estimate attwidth according to pg_attributes*/
			Form_pg_attribute att = (Form_pg_attribute) GETSTRUCT(attTuple);
			estimateColumnWidth(attWidth, &i, att, false);
			i--;

			int32 stawidth = 0;
			/*Step2: adjust addwidth according to pg_statistic*/
			switch (att->atttypid)
			{
				case HAWQ_TYPE_VARCHAR:
				case HAWQ_TYPE_TEXT:
				case HAWQ_TYPE_XML:
				case HAWQ_TYPE_PATH:
				case HAWQ_TYPE_POLYGON:
					stawidth = get_attavgwidth(rel_oid, att_id);
					if(stawidth != 0)
						attWidth[i] = stawidth;
					break;
				case HAWQ_TYPE_VARBIT:
					stawidth = get_attavgwidth(rel_oid, att_id);
					if(stawidth != 0)
						attWidth[i] = stawidth + 4;
					break;
				default:
					break;
			}
		}
		recordWidth += attWidth[i];
	}

	/* Reverse through the to-be-scanned attribute list, sum up the width */
	Assert (1 <= list_length(attr_list));
	foreach(cell, attr_list)
	{
		AttrNumber att_id = lfirst_int(cell);
		Assert(1 <= att_id);
		Assert(att_id <= attrNum);
		attsWidth += attWidth[att_id - 1];	/*sum up the attribute width in the to-be-scanned list*/
	}
Exemplo n.º 24
0
/*
 * get next tuple in in-memory heap table.
 */
HeapTuple
InMemHeap_GetNext(InMemHeapScanDesc scan, ScanDirection direction)
{
    bool valid = true;

    InMemHeapTuple pmemtup = NULL;

    Assert(NULL != scan);

    if (scan->hashIndexOk)
    {
        if (FALSE == scan->indexScanInitialized)
        {
            Oid key;
            bool found;

            key = DatumGetObjectId(scan->rs_key[scan->hashKeyIndexInScanKey].sk_argument);

            MemHeapHashIndexEntry *entry;
            entry = (MemHeapHashIndexEntry *) hash_search(scan->rs_rd->hashIndex, &key,
                    HASH_FIND, &found);

            if (found)
            {
            	if (BackwardScanDirection == direction)
            	{
            		/* if direction is backward, reverse list */
            		scan->indexReverseList = list_reverse_ints(entry->values);
            		entry->values = scan->indexReverseList;
            	}
                scan->indexNext = list_head(entry->values);
            }
            else
            	scan->indexNext = NULL;

            scan->indexScanInitialized = TRUE;
            scan->indexScanKey = key;
        }

        for (; scan->indexNext != NULL;
                scan->indexNext = lnext(scan->indexNext))
        {
            int32 index = lfirst_int(scan->indexNext);

            elog(DEBUG1, "read index %d key %d for relation %s", index, scan->indexScanKey, scan->rs_rd->relname);

            pmemtup = &scan->rs_rd->tuples[index];
            HeapKeyTest(pmemtup->tuple, RelationGetDescr(scan->rs_rd->rel),
                    scan->rs_nkeys, scan->rs_key, &valid);

            if (!valid)
            {
                continue;
            }

            scan->rs_ctup = pmemtup->tuple;
            scan->indexNext = lnext(scan->indexNext);
            return scan->rs_ctup;
        }
    }
    else
    {
    	/* for backward scan, change direction of iterator */
    	while (InMemHeap_GetNextIndex(scan, direction))
        {
            pmemtup = &scan->rs_rd->tuples[scan->rs_index];

            Assert(NULL != pmemtup->tuple);

            if (scan->rs_key != NULL)
            {
                Assert(NULL != scan->rs_rd->rel);
                HeapKeyTest(pmemtup->tuple, RelationGetDescr(scan->rs_rd->rel),
                        scan->rs_nkeys, scan->rs_key, &valid);
            }

            if (!valid)
            {
                continue;
            }

            scan->rs_ctup = pmemtup->tuple;
            return scan->rs_ctup;
        }
    }

    /*
     * read from local read only heap table.
     */
    if (NULL != scan->hscan)
    {
        return heap_getnext(scan->hscan, direction);
    }

    return NULL ;
}
Exemplo n.º 25
0
static void
ServiceListenLoop(ServiceCtrl *serviceCtrl)
{
	ServiceConfig *serviceConfig = (ServiceConfig*)serviceCtrl->serviceConfig;

	uint8 		*inputBuff;
	int			n,
				highsock = 0,
				newsockfd;
	mpp_fd_set	rset,
				rrset;

	struct sockaddr_in addr;
	socklen_t	addrlen;

	List   *connectedSockets = NIL;
	ListCell   *cell;

	Assert(TopMemoryContext != NULL);
	MemoryContextSwitchTo(TopMemoryContext);
	Assert(CurrentMemoryContext == TopMemoryContext);

	/*
	 * Setup scratch buffer.
	 */
	inputBuff = palloc(serviceConfig->requestLen);

	MPP_FD_ZERO(&rset);
	MPP_FD_SET(serviceCtrl->listenerFd, &rset);
	highsock = serviceCtrl->listenerFd + 1;

	/* we'll handle many incoming sockets but keep the sockets in blocking
	 * mode since we are dealing with very small messages.
	 */
	while(true)
	{
		struct timeval shutdownTimeout = {1,0};		// 1 second.
			// Use local variable since select modifies
			// the timeout parameter with remaining time.

		CHECK_FOR_INTERRUPTS();

		if (serviceConfig->ServiceShutdownRequested())
		{
			if (serviceConfig->ServiceShutdown != NULL)
			{
				serviceConfig->ServiceShutdown();
			}
			break;
		}

		/* no need to live on if postmaster has died */
		if (!PostmasterIsAlive(true))
		{
			if (serviceConfig->ServicePostmasterDied != NULL)
			{
				serviceConfig->ServicePostmasterDied();
			}
			else
			{
				ereport(LOG,
						(errmsg("exiting because postmaster has died")));
				proc_exit(1);
			}
		}

		memcpy(&rrset, &rset, sizeof(mpp_fd_set));

		n = select(highsock + 1, (fd_set *)&rrset, NULL, NULL, &shutdownTimeout);
		if (n == 0 || (n < 0 && errno == EINTR))
		{
			/* intr or timeout: Have we been here too long ? */
			continue;
		}

		if (n < 0)
		{
			/* this may be a little severe, but if we error on select()
			 * we'll just go ahead and blow up.  This will result in the
			 * postmaster re-spawning a new process.
			 */
			ereport(ERROR, (errcode(ERRCODE_GP_INTERCONNECTION_ERROR),
							 errmsg("'%s': error during select() call (error:%d).",
			     			        serviceConfig->title, errno)));
			break;
		}

		/* is it someone tickling our listener port? */
		if (MPP_FD_ISSET(serviceCtrl->listenerFd, &rrset))
		{
            addrlen = sizeof(addr);
			if ((newsockfd = accept(serviceCtrl->listenerFd,
				                    (struct sockaddr *) & addr,
				                    &addrlen)) < 0)
			{
				/*
				 * TODO: would be nice to read the errno and try and provide
				 * more useful info as to why this happened.
				 */
				ereport(NOTICE, (errcode(ERRCODE_GP_INTERCONNECTION_ERROR),
							 	 errmsg("'%s': error from client connection: %s)",
				     				    serviceConfig->title,
				     				    strerror(errno))));
			}

			/* make socket non-blocking BEFORE we connect. */
			if (!pg_set_noblock(newsockfd))
			{
				/*
				 * TODO: would be nice to read the errno and try and provide
				 * more useful info as to why this happened.
				 */
				ereport(NOTICE, (errcode(ERRCODE_GP_INTERCONNECTION_ERROR),
							 	 errmsg("'%s': could not set outbound socket to non-blocking mode: %s",
									    serviceConfig->title,
									    strerror(errno))));
			}

			if (newsockfd > highsock)
				highsock = newsockfd + 1;

			MPP_FD_SET(newsockfd, &rset);

			/*
			 * Read connection message.
			 */
			// UNDONE: temporarily turn off new connection flag...
			if( !ServiceProcessRequest(serviceCtrl, newsockfd, inputBuff, false))
			{
				/* close it down */
				MPP_FD_CLR( newsockfd, &rset);
				shutdown(newsockfd, SHUT_WR);
				close(newsockfd);
			}
			else
			{
				connectedSockets = lappend_int(connectedSockets, newsockfd);
			}

		}


		/* loop through all of our established sockets */
		cell = list_head(connectedSockets);
		while (cell != NULL)
		{
			int	fd = lfirst_int(cell);

			/* get the next cell ready before we delete */
			cell = lnext(cell);

			if (MPP_FD_ISSET(fd, &rrset))
			{
				if( !ServiceProcessRequest(serviceCtrl, fd, inputBuff, false))
				{
					/* close it down */
					MPP_FD_CLR( fd, &rset);
					connectedSockets = list_delete_int(connectedSockets, fd);
					shutdown(fd, SHUT_WR);
					close(fd);
				}
			}
		}
	}

	ereport(LOG,
			(errmsg("normal shutdown")));
	proc_exit(0);

}
Exemplo n.º 26
0
/*
 * Return the integer value contained in the n'th element of the
 * specified list.
 */
int
list_nth_int(const List *list, int n)
{
	Assert(IsIntegerList(list));
	return lfirst_int(list_nth_cell(list, n));
}
Exemplo n.º 27
0
/*
 * find_all_inheritors -
 *		Returns a list of relation OIDs including the given rel plus
 *		all relations that inherit from it, directly or indirectly.
 *		Optionally, it also returns the number of parents found for
 *		each such relation within the inheritance tree rooted at the
 *		given rel.
 *
 * The specified lock type is acquired on all child relations (but not on the
 * given rel; caller should already have locked it).  If lockmode is NoLock
 * then no locks are acquired, but caller must beware of race conditions
 * against possible DROPs of child relations.
 */
List *
find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
{
	/* hash table for O(1) rel_oid -> rel_numparents cell lookup */
	HTAB	   *seen_rels;
	HASHCTL		ctl;
	List	   *rels_list,
			   *rel_numparents;
	ListCell   *l;

	memset(&ctl, 0, sizeof(ctl));
	ctl.keysize = sizeof(Oid);
	ctl.entrysize = sizeof(SeenRelsEntry);
	ctl.hcxt = CurrentMemoryContext;

	seen_rels = hash_create("find_all_inheritors temporary table",
							32, /* start small and extend */
							&ctl,
							HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);

	/*
	 * We build a list starting with the given rel and adding all direct and
	 * indirect children.  We can use a single list as both the record of
	 * already-found rels and the agenda of rels yet to be scanned for more
	 * children.  This is a bit tricky but works because the foreach() macro
	 * doesn't fetch the next list element until the bottom of the loop.
	 */
	rels_list = list_make1_oid(parentrelId);
	rel_numparents = list_make1_int(0);

	foreach(l, rels_list)
	{
		Oid			currentrel = lfirst_oid(l);
		List	   *currentchildren;
		ListCell   *lc;

		/* Get the direct children of this rel */
		currentchildren = find_inheritance_children(currentrel, lockmode);

		/*
		 * Add to the queue only those children not already seen. This avoids
		 * making duplicate entries in case of multiple inheritance paths from
		 * the same parent.  (It'll also keep us from getting into an infinite
		 * loop, though theoretically there can't be any cycles in the
		 * inheritance graph anyway.)
		 */
		foreach(lc, currentchildren)
		{
			Oid			child_oid = lfirst_oid(lc);
			bool		found;
			SeenRelsEntry *hash_entry;

			hash_entry = hash_search(seen_rels, &child_oid, HASH_ENTER, &found);
			if (found)
			{
				/* if the rel is already there, bump number-of-parents counter */
				lfirst_int(hash_entry->numparents_cell)++;
			}
			else
			{
				/* if it's not there, add it. expect 1 parent, initially. */
				rels_list = lappend_oid(rels_list, child_oid);
				rel_numparents = lappend_int(rel_numparents, 1);
				hash_entry->numparents_cell = rel_numparents->tail;
			}
		}