Esempio n. 1
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);
	}
Esempio n. 2
0
CHURL_HANDLE churl_init_upload(const char* url, CHURL_HEADERS headers)
{
	churl_context* context = churl_new_context();
	create_curl_handle(context);
	context->upload = true;
	clear_error_buffer(context);

	set_curl_option(context, CURLOPT_URL, url);
	set_curl_option(context, CURLOPT_VERBOSE, (const void*)FALSE);
	set_curl_option(context, CURLOPT_ERRORBUFFER, context->curl_error_buffer);
	set_curl_option(context, CURLOPT_IPRESOLVE, (const void*)CURL_IPRESOLVE_V4);
	set_curl_option(context, CURLOPT_POST, (const void*)TRUE);
	set_curl_option(context, CURLOPT_READFUNCTION, read_callback);
	set_curl_option(context, CURLOPT_READDATA, context);
	set_curl_option(context, CURLOPT_WRITEFUNCTION, write_callback);
	set_curl_option(context, CURLOPT_WRITEDATA, context);
	set_curl_option(context, CURLOPT_HEADERFUNCTION, header_callback);
	set_curl_option(context, CURLOPT_HEADERDATA, context);
	churl_headers_append(headers, "Content-Type", "application/octet-stream");
	churl_headers_append(headers, "Transfer-Encoding", "chunked");
	churl_headers_append(headers, "Expect", "100-continue");
	churl_headers_set(context, headers);

	print_http_headers(headers);
	setup_multi_handle(context);

	return (CHURL_HANDLE)context;
}
Esempio n. 3
0
CHURL_HANDLE churl_init_upload(const char* url, CHURL_HEADERS headers)
{
	churl_context* context = churl_init(url, headers);

	context->upload = true;

	set_curl_option(context, CURLOPT_POST, (const void*) TRUE);
	set_curl_option(context, CURLOPT_READFUNCTION, read_callback);
	set_curl_option(context, CURLOPT_READDATA, context);
	churl_headers_append(headers, "Content-Type", "application/octet-stream");
	churl_headers_append(headers, "Transfer-Encoding", "chunked");
	churl_headers_append(headers, "Expect", "100-continue");

	return (CHURL_HANDLE)context;
}
Esempio n. 4
0
/*
 * get list of data nodes' rest servers,
 * and choose one (based on modulo segment id).
 * if pxf_isilon is true, there are no PXF instances on the datanodes.
 * TODO: add locality
 */
PxfServer* get_pxf_server(GPHDUri* gphd_uri, const Relation rel)
{
	ClientContext client_context; /* holds the communication info */
	PxfInputData inputData = {0};
	List	 	*rest_servers = NIL;
	ListCell 	*rest_server_c = NULL;
	PxfServer *found_server = NULL;
	PxfServer *ret_server = (PxfServer*)palloc0(sizeof(PxfServer));
	char		*server_ip = NULL;
	int 		 server_index = 0;

	Assert(gphd_uri);

	/* init context */
	init_client_context(&client_context);
	client_context.http_headers = churl_headers_init();

	/* set HTTP header that guarantees response in JSON format */
	churl_headers_append(client_context.http_headers, REST_HEADER_JSON_RESPONSE, NULL);
	if (!client_context.http_headers)
	{
		return NULL;
	}

	/*
	 * Enrich the curl HTTP header
	 */
	inputData.headers = client_context.http_headers;
	inputData.gphduri = gphd_uri;
	inputData.rel = rel;
	inputData.filterstr = NULL; /* We do not supply filter data to the HTTP header */
	add_delegation_token(&inputData);
	build_http_header(&inputData);

	int port = atoi(gphd_uri->port);

	if (!pxf_isilon)
	{
		/* send request */
		rest_servers = get_datanode_rest_servers(gphd_uri, &client_context);
		foreach(rest_server_c, rest_servers)
		{
			PxfServer *rest_server = (PxfServer*)lfirst(rest_server_c);
			/* In case there are several rest servers on the same host, we assume
			 * there are multiple DN residing together.
			 * The port is incremented by one, to match singlecluster convention */
			if (pxf_service_singlecluster)
			{
				if (server_ip == NULL)
				{
					server_ip = rest_server->host;
				}
				else if (are_ips_equal(server_ip, rest_server->host))
				{
					port++;
				}
			}
			rest_server->port = port;
		}
Esempio n. 5
0
void churl_headers_override(CHURL_HEADERS headers,
							const char* key,
							const char* value)
{

	churl_settings* settings = (churl_settings*)headers;
	struct curl_slist* header_cell = settings->headers;
	char* key_option = NULL;
	char* header_data = NULL;

	/* key must not be empty */
	Assert(key != NULL);

	/* key to compare with in the headers */
	key_option = build_header_str("%s:%s", key, value ? "" : NULL);

	/* find key in headers list */
	while (header_cell != NULL)
	{
		header_data = header_cell->data;

		if (strncmp(key_option, header_data, strlen(key_option)) == 0)
		{
			elog(DEBUG2, "churl_headers_override: Found existing header %s with key %s (for new value %s)",
				 header_data, key_option, value);
			break;
		}
		header_cell = header_cell->next;
	}

	if (header_cell != NULL) /* found key */
	{
		char* new_data = build_header_str("%s: %s", key, value);
		char* old_data = header_cell->data;
		header_cell->data = strdup(new_data);
		elog(DEBUG4, "churl_headers_override: new data: %s, old data: %s", new_data, old_data);
		free(old_data);
		pfree(new_data);
	}
	else
	{
		churl_headers_append(headers, key, value);
	}

	pfree(key_option);
}
Esempio n. 6
0
void append_churl_header_if_exists(gphadoop_context* context, const char* key, const char* value)
{
	if (value)
		churl_headers_append(context->churl_headers, key, value);
}
Esempio n. 7
0
/* 
 * Add key/value pairs to connection header. 
 * These values are the context of the query and used 
 * by the remote component. 
 */
void build_http_header(PxfInputData *input)
{
	extvar_t ev;
	CHURL_HEADERS headers = input->headers; 
	GPHDUri *gphduri = input->gphduri;
	Relation rel = input->rel;
	char *filterstr = input->filterstr;
	ProjectionInfo *proj_info = input->proj_info;
	
	if (rel != NULL)
	{
		/* format */
		ExtTableEntry *exttbl = GetExtTableEntry(rel->rd_id);
        /* pxf treats CSV as TEXT */
		char* format = get_format_name(exttbl->fmtcode);
		churl_headers_append(headers, "X-GP-FORMAT", format);
		
		/* Record fields - name and type of each field */
		add_tuple_desc_httpheader(headers, rel);
	}
	
	if (proj_info != NULL && proj_info->pi_isVarList)
	{
		List* qualsAttributes = extractPxfAttributes(input->quals);
		/* projection information is incomplete if columns from WHERE clause wasn't extracted */
		if (qualsAttributes !=  NIL || list_length(input->quals) == 0)
		{
			add_projection_desc_httpheader(headers, proj_info, qualsAttributes);
		}
		else
			elog(DEBUG2, "Query will not be optimized to use projection information");
	}

	/* GP cluster configuration */
	external_set_env_vars(&ev, gphduri->uri, false, NULL, NULL, false, 0);
	
	churl_headers_append(headers, "X-GP-SEGMENT-ID", ev.GP_SEGMENT_ID);
	churl_headers_append(headers, "X-GP-SEGMENT-COUNT", ev.GP_SEGMENT_COUNT);
	churl_headers_append(headers, "X-GP-XID", ev.GP_XID);
	
	/* Report alignment size to remote component
	 * GPDBWritable uses alignment that has to be the same as
	 * in the C code.
	 * Since the C code can be compiled for both 32 and 64 bits,
	 * the alignment can be either 4 or 8.
	 */
	add_alignment_size_httpheader(headers);
	
	/* headers for uri data */
	churl_headers_append(headers, "X-GP-URL-HOST", gphduri->host);
	churl_headers_append(headers, "X-GP-URL-PORT", gphduri->port);
	churl_headers_append(headers, "X-GP-DATA-DIR", gphduri->data);

	/* location options */
	add_location_options_httpheader(headers, gphduri);
	
	/* full uri */
	churl_headers_append(headers, "X-GP-URI", gphduri->uri);
	
	/* filters */
	if (filterstr)
	{
		churl_headers_append(headers, "X-GP-HAS-FILTER", "1");
		churl_headers_append(headers, "X-GP-FILTER", filterstr);
	}
	else
		churl_headers_append(headers, "X-GP-HAS-FILTER", "0");

	add_delegation_token_headers(headers, input);
	add_remote_credentials(headers);
}
Esempio n. 8
0
/* 
 * Report tuple description to remote component 
 * Currently, number of attributes, attributes names, types and types modifiers
 * Each attribute has a pair of key/value 
 * where X is the number of the attribute
 * X-GP-ATTR-NAMEX - attribute X's name 
 * X-GP-ATTR-TYPECODEX - attribute X's type OID (e.g, 16)
 * X-GP-ATTR-TYPENAMEX - attribute X's type name (e.g, "boolean")
 * optional - X-GP-ATTR-TYPEMODX-COUNT - total number of modifier for attribute X
 * optional - X-GP-ATTR-TYPEMODX-Y - attribute X's modifiers Y (types which have precision info, like numeric(p,s))
 */
static void add_tuple_desc_httpheader(CHURL_HEADERS headers, Relation rel)
{	
    char long_number[INT32_CHAR_SIZE];
    StringInfoData formatter;	
    TupleDesc tuple;		
    initStringInfo(&formatter);
	
    /* Get tuple description itself */	
    tuple = RelationGetDescr(rel);	
	
    /* Convert the number of attributes to a string */	
    pg_ltoa(tuple->natts, long_number);	
    churl_headers_append(headers, "X-GP-ATTRS", long_number);
	
    /* Iterate attributes */	
    for (int i = 0; i < tuple->natts; ++i)		
    {		
        /* Add a key/value pair for attribute name */		
        resetStringInfo(&formatter);		
        appendStringInfo(&formatter, "X-GP-ATTR-NAME%u", i);		
        churl_headers_append(headers, formatter.data, tuple->attrs[i]->attname.data);
		
		/* Add a key/value pair for attribute type */		
        resetStringInfo(&formatter);		
        appendStringInfo(&formatter, "X-GP-ATTR-TYPECODE%u", i);
        pg_ltoa(tuple->attrs[i]->atttypid, long_number);		
        churl_headers_append(headers, formatter.data, long_number);

        /* Add a key/value pair for attribute type name */
        resetStringInfo(&formatter);
        appendStringInfo(&formatter, "X-GP-ATTR-TYPENAME%u", i);
        churl_headers_append(headers, formatter.data, TypeOidGetTypename(tuple->attrs[i]->atttypid));

		/* Add attribute type modifiers if any*/
		if (tuple->attrs[i]->atttypmod > -1)
		{
			switch (tuple->attrs[i]->atttypid)
			{
				case NUMERICOID:
				{
					resetStringInfo(&formatter);
					appendStringInfo(&formatter, "X-GP-ATTR-TYPEMOD%u-COUNT", i);
					pg_ltoa(2, long_number);
					churl_headers_append(headers, formatter.data, long_number);


					/* precision */
					resetStringInfo(&formatter);
					appendStringInfo(&formatter, "X-GP-ATTR-TYPEMOD%u-%u", i, 0);
					pg_ltoa((tuple->attrs[i]->atttypmod >> 16) & 0xffff, long_number);
					churl_headers_append(headers, formatter.data, long_number);

					/* scale */
					resetStringInfo(&formatter);
					appendStringInfo(&formatter, "X-GP-ATTR-TYPEMOD%u-%u", i, 1);
					pg_ltoa((tuple->attrs[i]->atttypmod - VARHDRSZ) & 0xffff, long_number);
					churl_headers_append(headers, formatter.data, long_number);
					break;
				}
				case CHAROID:
				case BPCHAROID:
				case VARCHAROID:
				{
					resetStringInfo(&formatter);
					appendStringInfo(&formatter, "X-GP-ATTR-TYPEMOD%u-COUNT", i);
					pg_ltoa(1, long_number);
					churl_headers_append(headers, formatter.data, long_number);

					resetStringInfo(&formatter);
					appendStringInfo(&formatter, "X-GP-ATTR-TYPEMOD%u-%u", i, 0);
					pg_ltoa((tuple->attrs[i]->atttypmod - VARHDRSZ), long_number);
					churl_headers_append(headers, formatter.data, long_number);
					break;
				}
				case VARBITOID:
				case BITOID:
				case TIMESTAMPOID:
				case TIMESTAMPTZOID:
				case TIMEOID:
				case TIMETZOID:
				{
					resetStringInfo(&formatter);
					appendStringInfo(&formatter, "X-GP-ATTR-TYPEMOD%u-COUNT", i);
					pg_ltoa(1, long_number);
					churl_headers_append(headers, formatter.data, long_number);

					resetStringInfo(&formatter);
					appendStringInfo(&formatter, "X-GP-ATTR-TYPEMOD%u-%u", i, 0);
					pg_ltoa((tuple->attrs[i]->atttypmod), long_number);
					churl_headers_append(headers, formatter.data, long_number);
					break;
				}
				case INTERVALOID:
				{
					resetStringInfo(&formatter);
					appendStringInfo(&formatter, "X-GP-ATTR-TYPEMOD%u-COUNT", i);
					pg_ltoa(1, long_number);
					churl_headers_append(headers, formatter.data, long_number);

					resetStringInfo(&formatter);
					appendStringInfo(&formatter, "X-GP-ATTR-TYPEMOD%u-%u", i, 0);
					pg_ltoa(INTERVAL_PRECISION(tuple->attrs[i]->atttypmod), long_number);
					churl_headers_append(headers, formatter.data, long_number);
					break;
				}
				default:
					elog(DEBUG5, "add_tuple_desc_httpheader: unsupported type %d ", tuple->attrs[i]->atttypid);
					break;
			}
		}
	}
	
	pfree(formatter.data);
}
Esempio n. 9
0
/* Report alignment size to remote component
 * GPDBWritable uses alignment that has to be the same as
 * in the C code. 
 * Since the C code can be compiled for both 32 and 64 bits, 
 * the alignment can be either 4 or 8. 
 */
static void add_alignment_size_httpheader(CHURL_HEADERS headers)
{	
    char tmp[sizeof(char*)];	
    pg_ltoa(sizeof(char*), tmp);	
    churl_headers_append(headers, "X-GP-ALIGNMENT", tmp);	
}