long long oph_id_to_index(UDF_INIT * initid, UDF_ARGS * args, char *is_null, char *error)
{
	long long size, id = *((long long *) args->args[0]) - 1, index = id;
	if (id < 0) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Invalid value %d\n", id);
		*is_null = 0;
		*error = 1;
		return -1;
	}
	unsigned int counter = 1;
	while (counter < args->arg_count) {
		size = *((long long *) args->args[counter++]);
		index = id % size;
		id = (id - index) / size;
	}
	*is_null = 0;
	*error = 0;
	return index + 1;
}
/* Returns the latestForwarded_table_entry pointer to the latestForwardedTable
*  entry representing the neighbor node address passed as a parameter. If
*  no such neighbor exists, returns NULL.
*/
latestForwarded_table_entry* latestForwardedTableFind(rimeaddr_t *neighbor_p) {
	pmesg(200, "%s :: %s :: Line #%d\n", __FILE__, __func__, __LINE__);
	static uint8_t i = 0;
	static bool isBroadcast = 0;
  
  isBroadcast = rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                                &rimeaddr_null);
	if (isBroadcast)
		return NULL;

	for (i = 0; i < latestForwardedTableActive; i++) {
		if (rimeaddr_cmp(&(latestForwardedTable[i].neighbor), neighbor_p))
		break;
	}

	if(i == latestForwardedTableActive)
		return NULL;

	return &(latestForwardedTable[i]);
}
void conditionalFQDiscard() {
	pmesg(200, "%s :: %s :: Line #%d\n", __FILE__, __func__, __LINE__);

	static fe_queue_entry_t* discardQe;// = memb_alloc(&send_stack_mem); 

	if(list_length(send_stack) >= SEND_STACK_SIZE) {

		discardQe = list_chop(send_stack);
		list_remove(message_pool, discardQe -> msg);
		memb_free(&message_pool_mem, discardQe -> msg);

		list_remove(q_entry_pool, discardQe);
		memb_free(&q_entry_pool_mem, discardQe);

#ifdef VIRTQ 
		//	Dropped a data packet, increase virtual queue size
		virtualQueueSize++;
#endif
	}
}
int oph_hier_get_attribute(const char *name, oph_hier_attribute * attribute, const char *hierarchy, oph_hier_document * document)
{
	if (!name || !strlen(name)) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Property '%s' not given\n", OPH_HIER_STR_NAME);
		return OPH_HIER_DATA_ERR;
	}
	if (!hierarchy || !strlen(hierarchy))
		pmesg(LOG_WARNING, __FILE__, __LINE__, "Hierarchy not given\n", OPH_HIER_STR_NAME);
	int result;
	if ((result = oph_hier_basic_control(document)) != OPH_HIER_OK)
		return result;
	xmlXPathContextPtr context = xmlXPathNewContext(document->document);
	if (!context) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Context is not gettable\n");
		return OPH_HIER_SYSTEM_ERR;
	}
	char target[OPH_HIER_MAX_STRING_LENGTH];
	if (hierarchy && (strlen(hierarchy) > 0))
		sprintf(target, "//%s[@%s='%s']/%s[@%s='%s']", OPH_HIER_STR_HIERARCHY, OPH_HIER_STR_NAME, hierarchy, OPH_HIER_STR_ATTRIBUTE, OPH_HIER_STR_LONG_NAME, name);
	else
		sprintf(target, "//%s[@%s()='%s']", OPH_HIER_STR_ATTRIBUTE, OPH_HIER_STR_LONG_NAME, name);
	xmlXPathObjectPtr object = xmlXPathEvalExpression((xmlChar *) target, context);
	if (!object) {
		xmlXPathFreeContext(context);
		pmesg(LOG_ERROR, __FILE__, __LINE__, "XPath error\n");
		return OPH_HIER_SYSTEM_ERR;
	}
	xmlNodeSetPtr nodeset = object->nodesetval;
	if (!nodeset || !nodeset->nodeNr) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "No attribute '%s'\n", name);
		result = OPH_HIER_DATA_ERR;
	} else if ((nodeset->nodeNr > 1) && hierarchy && (strlen(hierarchy) > 0)) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Malformed file\n");
		result = OPH_HIER_XML_ERR;
	} else
		result = _oph_hier_get_attribute(nodeset->nodeTab[0], attribute);
	xmlXPathFreeObject(object);
	xmlXPathFreeContext(context);
	if (result == OPH_HIER_OK)
		pmesg(LOG_DEBUG, __FILE__, __LINE__, "Attribute '%s' read\n", name);
	return result;
}
int memory_check() // Check for memory swap
{
	struct sysinfo info;

	if (pthread_rwlock_wrlock(&syslock)) return OPH_SERVER_UTIL_ERROR;

	if (sysinfo(&info))
	{
		pthread_rwlock_unlock(&syslock);
		return OPH_SERVER_UTIL_ERROR;
	}

	if (pthread_rwlock_unlock(&syslock)) return OPH_SERVER_UTIL_ERROR;

	if ((info.freeram + info.bufferram < OPH_MIN_MEMORY) && (info.totalswap - info.freeswap > OPH_MIN_MEMORY))
	{
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Out of memory\n");
		return OPH_SERVER_UTIL_ERROR;
	}

	return OPH_SERVER_UTIL_SUCCESS;
}
Example #6
0
int _oph_odb_update_session_label(ophidiadb * oDB, const char *sessionid, char *label, pthread_mutex_t * flag)
{
	if (!oDB || !sessionid) {
		pmesg_safe(flag, LOG_ERROR, __FILE__, __LINE__, "Null input parameter\n");
		return OPH_ODB_NULL_PARAM;
	}

	if (oph_odb_check_connection_to_ophidiadb(oDB)) {
		pmesg_safe(flag, LOG_ERROR, __FILE__, __LINE__, "Unable to reconnect to OphidiaDB.\n");
		return OPH_ODB_MYSQL_ERROR;
	}

	int id_session;
	if (_oph_odb_retrieve_session_id(oDB, sessionid, &id_session, flag)) {
		pmesg_safe(flag, LOG_ERROR, __FILE__, __LINE__, "Unable to retrieve session id\n");
		return OPH_ODB_MYSQL_ERROR;
	}

	char insertQuery[MYSQL_BUFLEN];
	int n = snprintf(insertQuery, MYSQL_BUFLEN, MYSQL_QUERY_UPDATE_OPHIDIADB_SESSION_LABEL, label ? label : "", id_session);

	if (n >= MYSQL_BUFLEN) {
		pmesg_safe(flag, LOG_ERROR, __FILE__, __LINE__, "Size of query exceed query limit.\n");
		return OPH_ODB_STR_BUFF_OVERFLOW;
	}

	if (mysql_set_server_option(oDB->conn, MYSQL_OPTION_MULTI_STATEMENTS_ON)) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "MySQL query error: %s\n", mysql_error(oDB->conn));
		return OPH_ODB_MYSQL_ERROR;
	}

	if (mysql_query(oDB->conn, insertQuery)) {
		pmesg_safe(flag, LOG_ERROR, __FILE__, __LINE__, "MySQL query error: %s\n", mysql_error(oDB->conn));
		return OPH_ODB_MYSQL_ERROR;
	}

	return OPH_ODB_SUCCESS;
}
/*---------------------------------------------------------------------------*/
void chooseAdvertiseTime() {

	pmesg(200, "%s :: %s :: Line #%d\n", __FILE__, __func__, __LINE__);
	static uint32_t rand =0;	

	//Create a 32bit pseudo random number
	rand = ((uint32_t)random_rand());
	rand = rand << 16;
	rand = rand | ((uint32_t)random_rand());

	t = currentInterval;
	t /= 2;
	t += rand % t;
	tHasPassed = false;
	isBeaconTimerPeriodic = false;
	ctimer_stop(&beacon_timer);

	#ifdef BEACON_ONLY
	timer_set(&beacon_timerTime, ULONG_MAX);
	#endif
	ctimer_set(&beacon_timer, t, beacon_timer_fired, 0);
  	timer_reset(&beacon_timerTime);  // Reset the tandem timer
}
// Thread unsafe
int oph_http_get(struct soap *soap)
{
	pmesg(LOG_DEBUG, __FILE__, __LINE__, "Received a HTTP GET Request\n");
	if (!oph_server_protocol || !oph_server_host || !oph_server_port) {
		pmesg(LOG_DEBUG, __FILE__, __LINE__, "Return SOAP Fault\n");
		return SOAP_GET_METHOD;
	}
	FILE *fd = NULL;
	char buffer[OPH_MAX_STRING_SIZE] = { '\0' }, *s = strchr(soap->path, '?');
	if (!s) {
		snprintf(buffer, OPH_MAX_STRING_SIZE, OPH_SERVER_STD_HTTP_RESPONSE, oph_server_protocol, oph_server_host, oph_server_port, oph_server_protocol, oph_server_host, oph_server_port,
			 oph_server_protocol, oph_server_host, oph_server_port);
		soap->http_content = "text/html";
		pmesg(LOG_DEBUG, __FILE__, __LINE__, "Return HTML description of web service\n");
	} else if (strcmp(s, "?wsdl")) {
		pmesg(LOG_DEBUG, __FILE__, __LINE__, "Return SOAP Fault\n");
		return SOAP_GET_METHOD;
	} else {
		snprintf(buffer, OPH_MAX_STRING_SIZE, OPH_SERVER_WSDL, oph_server_location);
		fd = fopen(buffer, "rb");
		if (!fd) {
			pmesg(LOG_DEBUG, __FILE__, __LINE__, "Return HTTP 'Not Found' error\n");
			return 404;
		}
		soap->http_content = "text/xml";
		pmesg(LOG_DEBUG, __FILE__, __LINE__, "Return WSDL description of web service\n");
	}
	soap_response(soap, SOAP_FILE);
	size_t r;
	if (fd) {
		for (;;) {
			r = fread(soap->tmpbuf, 1, sizeof(soap->tmpbuf), fd);
			if (!r)
				break;
			if (soap_send_raw(soap, soap->tmpbuf, r))
				break;
		}
		fclose(fd);
	} else {
		r = snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s", buffer);
		soap_send_raw(soap, soap->tmpbuf, r);
	}
	soap_end_send(soap);
	return SOAP_OK;
}
int _memory_get_frag(oph_iostore_handler * handle, oph_iostore_resource_id * res_id, oph_iostore_frag_record_set ** frag_record)
{
	if (!handle || !res_id || !res_id->id || !frag_record) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, MEMORY_LOG_NULL_INPUT_PARAM);
		logging(LOG_ERROR, __FILE__, __LINE__, MEMORY_LOG_NULL_INPUT_PARAM);
		return MEMORY_DEV_NULL_PARAM;
	}

	*frag_record = NULL;

	//Read resource id
	oph_iostore_frag_record_set *internal_record = *((oph_iostore_frag_record_set **) res_id->id);

	//Get in-memory copy of frag
/*  if(_memory_copy_frag_record_set(internal_record, frag_record) || frag_record == NULL){
    pmesg(LOG_ERROR, __FILE__, __LINE__, MEMORY_LOG_MEMORY_ERROR);
    logging(LOG_ERROR, __FILE__, __LINE__, MEMORY_LOG_MEMORY_ERROR);        
    return MEMORY_DEV_ERROR;
  }*/
	*frag_record = internal_record;

	return MEMORY_DEV_SUCCESS;
}
void stack_check_timer_fired(void){
	pmesg(200, "%s :: %s :: Line #%d\n", __FILE__, __func__, __LINE__);
	static bool bpIncrease = false;
	static uint16_t diffBackpressure =0;
	static uint16_t newLocalBackpressure =0;
	static uint32_t beacon_time =0;

	beacon_time = ULONG_MAX - (uint32_t)timer_remaining(&beacon_timerTime);
	newLocalBackpressure = list_length(send_stack) + sendQeOccupied + virtualQueueSize;

	if(beacon_time >= BEACON_TH_INTERVAL){ //recently we have not broadcast a beacon
	//update backpressure to other nodes
	if(oldLocalBackpressure < newLocalBackpressure) 
	  bpIncrease = true;

	if(bpIncrease)
	  diffBackpressure = newLocalBackpressure - oldLocalBackpressure;
	else
	  diffBackpressure = oldLocalBackpressure - newLocalBackpressure;  


	if(diffBackpressure>=DIFF_QUEUE_TH){       	
	  if( extraBeaconSending == false){ 
	    extraBeaconSending = true;
	  } else { return; }
	  beaconType = NORMAL_BEACON;
	  process_post(&sendBeaconTask, NULL, NULL);
	  skipExtraBeaconCnt=3;
	}
	} else {
	  if(skipExtraBeaconCnt>0) {
	    skipExtraBeaconCnt--;
	  }
	}

	oldLocalBackpressure = newLocalBackpressure;
}
/*---------------------------------------------------------------------------*/
void beacon_timer_fired(){
	pmesg(200, "%s :: %s :: Line #%d\n", __FILE__, __func__, __LINE__);
	#ifdef BEACON_ONLY    
	//	check stack size timer
 	if(ctimer_expired(&stack_check_timer)) {
		ctimer_set(&stack_check_timer, (clock_time_t)STACK_CHECK_INTERVAL, stack_check_timer_fired, NULL);
 	}
	#endif
	if (isRunningForwardingEngine) {
		if (!tHasPassed) {
			beaconType = NORMAL_BEACON;
			process_post(&sendBeaconTask, NULL, NULL);
 			remainingInterval();
		}
		else {
			decayInterval();
		}
 	}

	if(isBeaconTimerPeriodic == true){
		ctimer_set(&beacon_timer, BEACON_TIME, beacon_timer_fired, NULL);
    	timer_reset(&beacon_timerTime);  // Reset the tandem timer
  }
}
char *oph_sum_array_r(UDF_INIT * initid, UDF_ARGS * args, char *result, unsigned long *length, char *is_null, char *error)
{

	// Allocate space for the result_array; result_array[i] = measurea[i] + measureb[i]
	//initid->ptr=(char *)malloc(*(measure.length) * (core_sizeof(measure.type))); 
	if (!initid->ptr) {
		initid->ptr = (char *) malloc(args->lengths[0]);
		if (!initid->ptr) {
			pmesg(1, __FILE__, __LINE__, "Error allocating result string\n");
			*length = 0;
			*is_null = 1;
			*error = 1;
			return NULL;
		}
	}

	barrier_wait(&(((th_data *) (initid->extension))->barr_start));
	barrier_wait(&(((th_data *) (initid->extension))->barr_end));

	*length = args->lengths[0];
	*error = 0;
	*is_null = 0;
	return initid->ptr;
}
int core_oph_roll_up(oph_roll_up_param* param)
{
	if (param->rows < param->size)
	{
		oph_string* measure = (oph_string*)param->measure;
		unsigned long row_size = measure->numelem * param->result_elemsize;
		if (param->result_type != measure->type)
		{
			unsigned long i;
			char *input_ptr = measure->content, *output_ptr = param->result + param->rows*row_size;
			for (i=0; i<measure->numelem; ++i, input_ptr += measure->elemsize, output_ptr += param->result_elemsize)
			{
				if(core_oph_type_cast(input_ptr, output_ptr, measure->type, param->result_type))
				{
					pmesg(1,  __FILE__, __LINE__, "Unable to find result\n");
					return 1;
				}
			}
		}
		else memcpy(param->result + param->rows*row_size, measure->content, row_size);
		param->rows++;
	}
	return 0;
}
int oph_subset_size(oph_subset* subset, unsigned long long initial_size, unsigned long long* final_size, unsigned long long* sizes, int size_number)
{
	if (!subset)
	{
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Null pointer\n");
		return OPH_SUBSET_LIB_NULL_POINTER_ERR;
	}

	*final_size=0;
	unsigned long long j;

	if (!sizes || !size_number)
	{
		for (j=1; j<=initial_size; ++j) // It is not C-like indexing
			if (oph_subset_index_is_in_subset(j, subset)) (*final_size)++;
	}
	else
	{
		for (j=1; j<=initial_size; ++j) // It is not C-like indexing
			if (oph_subset_id_is_in_subset(j, subset, sizes, size_number)) (*final_size)++;
	}

	return OPH_SUBSET_LIB_OK;
}
char *oph_predicate2(UDF_INIT * initid, UDF_ARGS * args, char *result, unsigned long *length, char *is_null, char *error)
{
	oph_string measure;
	char *buffer;
	char **names;
	int count;
	oph_predicate2_param *param;

	int i = 0;

	if (core_set_type(&(measure), args->args[0], &(args->lengths[0]))) {
		pmesg(1, __FILE__, __LINE__, "Type not recognized\n");
		*length = 0;
		*is_null = 0;
		*error = 1;
		return NULL;
	}

	measure.content = args->args[2];
	measure.length = &(args->lengths[2]);
	measure.missingvalue = NULL;

	core_set_elemsize(&(measure));

	if (core_set_numelem(&(measure))) {
		pmesg(1, __FILE__, __LINE__, "Error on counting elements\n");
		*length = 0;
		*is_null = 0;
		*error = 1;
		return NULL;
	}

	if (!initid->ptr) {
		initid->ptr = (char *) malloc(sizeof(oph_predicate2_param));
		if (!initid->ptr) {
			pmesg(1, __FILE__, __LINE__, "Error allocating result string\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		param = (oph_predicate2_param *) initid->ptr;

		for (i = 0; i < 4; ++i)
			param->f[i] = NULL;
		param->occurrence = 0;	// ALL

		buffer = (char *) malloc(1 + args->lengths[3]);
		strncpy(buffer, args->args[3], args->lengths[3]);
		buffer[args->lengths[3]] = '\0';
		pthread_rwlock_wrlock(&lock);
		param->f[1] = evaluator_create(buffer);
		pthread_rwlock_unlock(&lock);
		free(buffer);
		if (!param->f[1]) {
			pmesg(1, __FILE__, __LINE__, "Error allocating evaluator\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		evaluator_get_variables(param->f[1], &names, &count);
		if (count > 1) {
			pmesg(1, __FILE__, __LINE__, "Too variables in expression\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		// Comparison operator
		if (core_set_comp(&param->op, args->args[4], &(args->lengths[4]))) {
			pmesg(1, __FILE__, __LINE__, "Comparison operator not recognized\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		if (args->args[5] && args->lengths[5]) {
			buffer = (char *) malloc(1 + args->lengths[5]);
			core_strncpy(buffer, args->args[5], &(args->lengths[5]));
			if (!strcasecmp(buffer, "nan"))
				sprintf(buffer, "0/0");
		} else
			buffer = strdup("0/0");
		pthread_rwlock_wrlock(&lock);
		param->f[2] = evaluator_create(buffer);
		pthread_rwlock_unlock(&lock);
		free(buffer);
		if (!param->f[2]) {
			pmesg(1, __FILE__, __LINE__, "Error allocating evaluator\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		evaluator_get_variables(param->f[2], &names, &count);
		if (count > 1) {
			pmesg(1, __FILE__, __LINE__, "Too variables in expression\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		if (args->args[6] && args->lengths[6]) {
			buffer = (char *) malloc(1 + args->lengths[6]);
			core_strncpy(buffer, args->args[6], &(args->lengths[6]));
			if (!strcasecmp(buffer, "nan"))
				sprintf(buffer, "0/0");
		} else
			buffer = strdup("0/0");
		pthread_rwlock_wrlock(&lock);
		param->f[3] = evaluator_create(buffer);
		pthread_rwlock_unlock(&lock);
		free(buffer);
		if (!param->f[3]) {
			pmesg(1, __FILE__, __LINE__, "Error allocating evaluator\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		evaluator_get_variables(param->f[3], &names, &count);
		if (count > 1) {
			pmesg(1, __FILE__, __LINE__, "Too variables in expression\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		oph_string output_array;
		core_set_type(&output_array, args->args[1], &(args->lengths[1]));
		if (!output_array.type) {
			pmesg(1, __FILE__, __LINE__, "Unable to recognize measures type\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		if (core_set_elemsize(&output_array)) {
			pmesg(1, __FILE__, __LINE__, "Unable to recognize measures type\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		param->result_type = output_array.type;
		param->result_elemsize = output_array.elemsize;

		param->length = output_array.elemsize * measure.numelem;
		param->f[0] = malloc(param->length);
		if (!param->f[0]) {
			pmesg(1, __FILE__, __LINE__, "Error allocating result string\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		if (args->arg_count > 7) {
			buffer = (char *) malloc(1 + args->lengths[7]);
			core_strncpy(buffer, args->args[7], &(args->lengths[7]));
			if (strcasecmp(buffer, OPH_PREDICATE2_ALL_OCCURRENCE)) {
				if (!strcasecmp(buffer, OPH_PREDICATE2_FIRST_OCCURRENCE) || !strcasecmp(buffer, OPH_PREDICATE2_BEGIN_OCCURRENCE))
					param->occurrence = 1;
				else if (!strcasecmp(buffer, OPH_PREDICATE2_LAST_OCCURRENCE) || !strcasecmp(buffer, OPH_PREDICATE2_END_OCCURRENCE))
					param->occurrence = -1;
				else {
					if (args->arg_type[7] == STRING_RESULT)
						param->occurrence = (long) strtol(buffer, NULL, 10);
					else
						param->occurrence = *((long long *) args->args[7]);
					if (param->occurrence < 1) {
						free(buffer);
						pmesg(1, __FILE__, __LINE__, "Unable to read occurrence\n");
						*length = 0;
						*is_null = 0;
						*error = 1;
						return NULL;
					}
				}
			}
			free(buffer);
		}
	} else
		param = (oph_predicate2_param *) initid->ptr;

	i = core_oph_predicate2(&measure, initid->ptr);
	if (i) {
		pmesg(1, __FILE__, __LINE__, "Unable to compute result\n");
		*length = 0;
		*is_null = 0;
		*error = 1;
		return NULL;
	}
	*length = param->length;
	*error = 0;
	*is_null = 0;
	return (char *) param->f[0];

}
int core_oph_predicate2(oph_stringPtr byte_array, char *result)
{
	unsigned long i, occurrence, occurrence_number = 0;
	unsigned short r;
	double res, temporary;
	oph_predicate2_param *_result = (oph_predicate2_param *) result;
	if (_result->occurrence < 0)
		occurrence = 1;
	else
		occurrence = (unsigned long) _result->occurrence;
	switch (byte_array->type) {
		case OPH_DOUBLE:
			{
				for (i = _result->occurrence < 0 ? byte_array->numelem - 1 : 0; (0 <= i) && (i < byte_array->numelem); _result->occurrence < 0 ? --i : ++i) {
					res = evaluator_evaluate_x(_result->f[1], *((double *) (byte_array->content + i * byte_array->elemsize)));
					switch (_result->op) {
						case OPH_GREATER_THAN_ZERO:
							{
								r = res > 0.0;
								break;
							}
						case OPH_LESS_THAN_ZERO:
							{
								r = res < 0.0;
								break;
							}
						case OPH_EQUAL_TO_ZERO:
							{
								r = res == 0.0;
								break;
							}
						case OPH_GREATER_OR_EQUAL_TO_ZERO:
							{
								r = res >= 0.0;
								break;
							}
						case OPH_LESS_OR_EQUAL_TO_ZERO:
							{
								r = res <= 0.0;
								break;
							}
						case OPH_NOT_EQUAL_TO_ZERO:
							{
								r = res != 0.0;
								break;
							}
						case OPH_NULL:
							{
								r = isnan(res);
								break;
							}
						default:
							pmesg(1, __FILE__, __LINE__, "Comparison value non recognized\n");
							return -1;
					}
					if (occurrence && r) {
						occurrence_number++;
						if (occurrence != occurrence_number)
							r = 0;
					}
					temporary = evaluator_evaluate_x(_result->f[r ? 2 : 3], *((double *) (byte_array->content + i * byte_array->elemsize)));
					if (core_oph_type_cast(&temporary, (((char *) _result->f[0]) + i * _result->result_elemsize), OPH_DOUBLE, _result->result_type, byte_array->missingvalue)) {
						pmesg(1, __FILE__, __LINE__, "Unable to find result\n");
						return 1;
					}
				}
				break;
			}
		case OPH_FLOAT:
			{
				for (i = _result->occurrence < 0 ? byte_array->numelem - 1 : 0; (0 <= i) && (i < byte_array->numelem); _result->occurrence < 0 ? --i : ++i) {
					res = evaluator_evaluate_x(_result->f[1], *((float *) (byte_array->content + i * byte_array->elemsize)));
					switch (_result->op) {
						case OPH_GREATER_THAN_ZERO:
							{
								r = res > 0.0;
								break;
							}
						case OPH_LESS_THAN_ZERO:
							{
								r = res < 0.0;
								break;
							}
						case OPH_EQUAL_TO_ZERO:
							{
								r = res == 0.0;
								break;
							}
						case OPH_GREATER_OR_EQUAL_TO_ZERO:
							{
								r = res >= 0.0;
								break;
							}
						case OPH_LESS_OR_EQUAL_TO_ZERO:
							{
								r = res <= 0.0;
								break;
							}
						case OPH_NOT_EQUAL_TO_ZERO:
							{
								r = res != 0.0;
								break;
							}
						case OPH_NULL:
							{
								r = isnan(res);
								break;
							}
						default:
							pmesg(1, __FILE__, __LINE__, "Comparison value non recognized\n");
							return -1;
					}
					if (occurrence && r) {
						occurrence_number++;
						if (occurrence != occurrence_number)
							r = 0;
					}
					temporary = evaluator_evaluate_x(_result->f[r ? 2 : 3], *((float *) (byte_array->content + i * byte_array->elemsize)));
					if (core_oph_type_cast(&temporary, (((char *) _result->f[0]) + i * _result->result_elemsize), OPH_DOUBLE, _result->result_type, byte_array->missingvalue)) {
						pmesg(1, __FILE__, __LINE__, "Unable to find result\n");
						return 1;
					}
				}
				break;
			}
		case OPH_INT:
			{
				for (i = _result->occurrence < 0 ? byte_array->numelem - 1 : 0; (0 <= i) && (i < byte_array->numelem); _result->occurrence < 0 ? --i : ++i) {
					res = evaluator_evaluate_x(_result->f[1], *((int *) (byte_array->content + i * byte_array->elemsize)));
					switch (_result->op) {
						case OPH_GREATER_THAN_ZERO:
							{
								r = res > 0.0;
								break;
							}
						case OPH_LESS_THAN_ZERO:
							{
								r = res < 0.0;
								break;
							}
						case OPH_EQUAL_TO_ZERO:
							{
								r = res == 0.0;
								break;
							}
						case OPH_GREATER_OR_EQUAL_TO_ZERO:
							{
								r = res >= 0.0;
								break;
							}
						case OPH_LESS_OR_EQUAL_TO_ZERO:
							{
								r = res <= 0.0;
								break;
							}
						case OPH_NOT_EQUAL_TO_ZERO:
							{
								r = res != 0.0;
								break;
							}
						case OPH_NULL:
							{
								r = isnan(res);
								break;
							}
						default:
							pmesg(1, __FILE__, __LINE__, "Comparison value non recognized\n");
							return -1;
					}
					if (occurrence && r) {
						occurrence_number++;
						if (occurrence != occurrence_number)
							r = 0;
					}
					temporary = evaluator_evaluate_x(_result->f[r ? 2 : 3], *((int *) (byte_array->content + i * byte_array->elemsize)));
					if (core_oph_type_cast(&temporary, (((char *) _result->f[0]) + i * _result->result_elemsize), OPH_DOUBLE, _result->result_type, byte_array->missingvalue)) {
						pmesg(1, __FILE__, __LINE__, "Unable to find result\n");
						return 1;
					}
				}
				break;
			}
		case OPH_SHORT:
			{
				for (i = _result->occurrence < 0 ? byte_array->numelem - 1 : 0; (0 <= i) && (i < byte_array->numelem); _result->occurrence < 0 ? --i : ++i) {
					res = evaluator_evaluate_x(_result->f[1], *((short *) (byte_array->content + i * byte_array->elemsize)));
					switch (_result->op) {
						case OPH_GREATER_THAN_ZERO:
							{
								r = res > 0.0;
								break;
							}
						case OPH_LESS_THAN_ZERO:
							{
								r = res < 0.0;
								break;
							}
						case OPH_EQUAL_TO_ZERO:
							{
								r = res == 0.0;
								break;
							}
						case OPH_GREATER_OR_EQUAL_TO_ZERO:
							{
								r = res >= 0.0;
								break;
							}
						case OPH_LESS_OR_EQUAL_TO_ZERO:
							{
								r = res <= 0.0;
								break;
							}
						case OPH_NOT_EQUAL_TO_ZERO:
							{
								r = res != 0.0;
								break;
							}
						case OPH_NULL:
							{
								r = isnan(res);
								break;
							}
						default:
							pmesg(1, __FILE__, __LINE__, "Comparison value non recognized\n");
							return -1;
					}
					if (occurrence && r) {
						occurrence_number++;
						if (occurrence != occurrence_number)
							r = 0;
					}
					temporary = evaluator_evaluate_x(_result->f[r ? 2 : 3], *((short *) (byte_array->content + i * byte_array->elemsize)));
					if (core_oph_type_cast(&temporary, (((char *) _result->f[0]) + i * _result->result_elemsize), OPH_DOUBLE, _result->result_type, byte_array->missingvalue)) {
						pmesg(1, __FILE__, __LINE__, "Unable to find result\n");
						return 1;
					}
				}
				break;
			}
		case OPH_BYTE:
			{
				for (i = _result->occurrence < 0 ? byte_array->numelem - 1 : 0; (0 <= i) && (i < byte_array->numelem); _result->occurrence < 0 ? --i : ++i) {
					res = evaluator_evaluate_x(_result->f[1], *((char *) (byte_array->content + i * byte_array->elemsize)));
					switch (_result->op) {
						case OPH_GREATER_THAN_ZERO:
							{
								r = res > 0.0;
								break;
							}
						case OPH_LESS_THAN_ZERO:
							{
								r = res < 0.0;
								break;
							}
						case OPH_EQUAL_TO_ZERO:
							{
								r = res == 0.0;
								break;
							}
						case OPH_GREATER_OR_EQUAL_TO_ZERO:
							{
								r = res >= 0.0;
								break;
							}
						case OPH_LESS_OR_EQUAL_TO_ZERO:
							{
								r = res <= 0.0;
								break;
							}
						case OPH_NOT_EQUAL_TO_ZERO:
							{
								r = res != 0.0;
								break;
							}
						case OPH_NULL:
							{
								r = isnan(res);
								break;
							}
						default:
							pmesg(1, __FILE__, __LINE__, "Comparison value non recognized\n");
							return -1;
					}
					if (occurrence && r) {
						occurrence_number++;
						if (occurrence != occurrence_number)
							r = 0;
					}
					temporary = evaluator_evaluate_x(_result->f[r ? 2 : 3], *((char *) (byte_array->content + i * byte_array->elemsize)));
					if (core_oph_type_cast(&temporary, (((char *) _result->f[0]) + i * _result->result_elemsize), OPH_DOUBLE, _result->result_type, byte_array->missingvalue)) {
						pmesg(1, __FILE__, __LINE__, "Unable to find result\n");
						return 1;
					}
				}
				break;
			}
		case OPH_LONG:
			{
				for (i = _result->occurrence < 0 ? byte_array->numelem - 1 : 0; (0 <= i) && (i < byte_array->numelem); _result->occurrence < 0 ? --i : ++i) {
					res = evaluator_evaluate_x(_result->f[1], *((long long *) (byte_array->content + i * byte_array->elemsize)));
					switch (_result->op) {
						case OPH_GREATER_THAN_ZERO:
							{
								r = res > 0.0;
								break;
							}
						case OPH_LESS_THAN_ZERO:
							{
								r = res < 0.0;
								break;
							}
						case OPH_EQUAL_TO_ZERO:
							{
								r = res == 0.0;
								break;
							}
						case OPH_GREATER_OR_EQUAL_TO_ZERO:
							{
								r = res >= 0.0;
								break;
							}
						case OPH_LESS_OR_EQUAL_TO_ZERO:
							{
								r = res <= 0.0;
								break;
							}
						case OPH_NOT_EQUAL_TO_ZERO:
							{
								r = res != 0.0;
								break;
							}
						case OPH_NULL:
							{
								r = isnan(res);
								break;
							}
						default:
							pmesg(1, __FILE__, __LINE__, "Comparison value non recognized\n");
							return -1;
					}
					if (occurrence && r) {
						occurrence_number++;
						if (occurrence != occurrence_number)
							r = 0;
					}
					temporary = evaluator_evaluate_x(_result->f[r ? 2 : 3], *((long long *) (byte_array->content + i * byte_array->elemsize)));
					if (core_oph_type_cast(&temporary, (((char *) _result->f[0]) + i * _result->result_elemsize), OPH_DOUBLE, _result->result_type, byte_array->missingvalue)) {
						pmesg(1, __FILE__, __LINE__, "Unable to find result\n");
						return 1;
					}
				}
				break;
			}
		default:
			pmesg(1, __FILE__, __LINE__, "Type non recognized\n");
			return -1;
	}
	return 0;
}
int workflow_validate_fco(oph_workflow * wf)
{
	if (!wf) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Null pointer!\n");
		return OPH_WORKFLOW_EXIT_BAD_PARAM_ERROR;
	}

	int i, k, kk, child;
	char flag[wf->tasks_num];
	unsigned int number;

	for (k = 0; k < wf->tasks_num; k++)
		wf->tasks[k].parent = wf->tasks[k].child = -1;

	for (k = 0; k < wf->tasks_num; k++) {
		if (!strncasecmp(wf->tasks[k].operator, OPH_OPERATOR_FOR, OPH_WORKFLOW_MAX_STRING)) {
			for (i = 0; i < wf->tasks_num; ++i)
				flag[i] = 1;
			number = workflow_number_of(wf, k, k, k, OPH_OPERATOR_ENDFOR, OPH_OPERATOR_FOR, flag, 0, &child);
			if (!number || (number > 1))
				break;
			for (i = 0; i < wf->tasks_num; ++i)
				if ((wf->tasks[i].parent == k) && strncasecmp(wf->tasks[k].operator, OPH_OPERATOR_ENDFOR, OPH_WORKFLOW_MAX_STRING) && !oph_workflow_is_child_of(wf, i, child))
					break;
			if (i < wf->tasks_num)
				break;
		} else if (!strncasecmp(wf->tasks[k].operator, OPH_OPERATOR_IF, OPH_WORKFLOW_MAX_STRING)) {
			for (i = 0; i < wf->tasks_num; ++i)
				flag[i] = 1;
			child = -1;
			number = workflow_number_of(wf, k, k, k, OPH_OPERATOR_ELSEIF, OPH_OPERATOR_IF, flag, 0, &child);
			if (number > 1)
				break;
			if (child >= 0) {
				for (i = 0; i < wf->tasks_num; ++i)
					if ((wf->tasks[i].parent == k) && strncasecmp(wf->tasks[k].operator, OPH_OPERATOR_ELSEIF, OPH_WORKFLOW_MAX_STRING) && !oph_workflow_is_child_of(wf, i, child))
						break;
				if (i < wf->tasks_num)
					break;
			} else {
				for (i = 0; i < wf->tasks_num; ++i)
					flag[i] = 1;
				child = -1;
				number = workflow_number_of(wf, k, k, k, OPH_OPERATOR_ELSE, OPH_OPERATOR_IF, flag, 0, &child);
				if (number > 1)
					break;
				if (child >= 0) {
					for (i = 0; i < wf->tasks_num; ++i)
						if ((wf->tasks[i].parent == k) && strncasecmp(wf->tasks[k].operator, OPH_OPERATOR_ELSE, OPH_WORKFLOW_MAX_STRING)
						    && !oph_workflow_is_child_of(wf, i, child))
							break;
					if (i < wf->tasks_num)
						break;
				}
			}
			for (i = 0; i < wf->tasks_num; ++i)
				flag[i] = 1;
			number = workflow_number_of(wf, k, k, k, OPH_OPERATOR_ENDIF, OPH_OPERATOR_IF, flag, 0, &child);
			if (!number && (number > 1))
				break;
			for (i = 0; i < wf->tasks_num; ++i)
				if ((wf->tasks[i].parent == k) && strncasecmp(wf->tasks[k].operator, OPH_OPERATOR_ENDIF, OPH_WORKFLOW_MAX_STRING) && !oph_workflow_is_child_of(wf, i, child))
					break;
			if (i < wf->tasks_num)
				break;
		} else if (!strncasecmp(wf->tasks[k].operator, OPH_OPERATOR_ELSEIF, OPH_WORKFLOW_MAX_STRING)) {
			kk = oph_gparent_of(wf, k);
			for (i = 0; i < wf->tasks_num; ++i)
				flag[i] = 1;
			child = -1;
			number = workflow_number_of(wf, k, k, kk, OPH_OPERATOR_ELSEIF, OPH_OPERATOR_IF, flag, 0, &child);
			if (number > 1)
				break;
			if (child >= 0) {
				for (i = 0; i < wf->tasks_num; ++i)
					if ((wf->tasks[i].parent == k) && strncasecmp(wf->tasks[k].operator, OPH_OPERATOR_ELSEIF, OPH_WORKFLOW_MAX_STRING) && !oph_workflow_is_child_of(wf, i, child))
						break;
				if (i < wf->tasks_num)
					break;
			} else {
				for (i = 0; i < wf->tasks_num; ++i)
					flag[i] = 1;
				child = -1;
				number = workflow_number_of(wf, k, k, kk, OPH_OPERATOR_ELSE, OPH_OPERATOR_IF, flag, 0, &child);
				if (number > 1)
					break;
				if (child >= 0) {
					for (i = 0; i < wf->tasks_num; ++i)
						if ((wf->tasks[i].parent == k) && strncasecmp(wf->tasks[k].operator, OPH_OPERATOR_ELSE, OPH_WORKFLOW_MAX_STRING)
						    && !oph_workflow_is_child_of(wf, i, child))
							break;
					if (i < wf->tasks_num)
						break;
				} else {
					for (i = 0; i < wf->tasks_num; ++i)
						flag[i] = 1;
					number = workflow_number_of(wf, k, k, kk, OPH_OPERATOR_ENDIF, OPH_OPERATOR_IF, flag, 0, &child);
					if (!number || (number > 1))
						break;
					for (i = 0; i < wf->tasks_num; ++i)
						if ((wf->tasks[i].parent == k) && strncasecmp(wf->tasks[k].operator, OPH_OPERATOR_ENDIF, OPH_WORKFLOW_MAX_STRING)
						    && !oph_workflow_is_child_of(wf, i, child))
							break;
					if (i < wf->tasks_num)
						break;
				}
			}
		} else if (!strncasecmp(wf->tasks[k].operator, OPH_OPERATOR_ELSE, OPH_WORKFLOW_MAX_STRING)) {
			kk = oph_gparent_of(wf, k);
			for (i = 0; i < wf->tasks_num; ++i)
				flag[i] = 1;
			number = workflow_number_of(wf, k, k, kk, OPH_OPERATOR_ENDIF, OPH_OPERATOR_IF, flag, 0, &child);
			if (!number || (number > 1))
				break;
			for (i = 0; i < wf->tasks_num; ++i)
				if ((wf->tasks[i].parent == k) && strncasecmp(wf->tasks[k].operator, OPH_OPERATOR_ENDIF, OPH_WORKFLOW_MAX_STRING) && !oph_workflow_is_child_of(wf, i, child))
					break;
			if (i < wf->tasks_num)
				break;
		}
	}
	if (k < wf->tasks_num) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Flow control operator '%s' is not set correctly!\n", wf->tasks[k].name);
		return OPH_WORKFLOW_EXIT_BAD_PARAM_ERROR;
	}

	for (k = 0; k < wf->tasks_num; k++)
		if (wf->tasks[k].parent < 0) {
			if (!strncasecmp(wf->tasks[k].operator, OPH_OPERATOR_ENDFOR, OPH_WORKFLOW_MAX_STRING))
				break;
			else if (!strncasecmp(wf->tasks[k].operator, OPH_OPERATOR_ELSEIF, OPH_WORKFLOW_MAX_STRING))
				break;
			else if (!strncasecmp(wf->tasks[k].operator, OPH_OPERATOR_ELSE, OPH_WORKFLOW_MAX_STRING))
				break;
			else if (!strncasecmp(wf->tasks[k].operator, OPH_OPERATOR_ENDIF, OPH_WORKFLOW_MAX_STRING))
				break;
		}
	if (k < wf->tasks_num) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Flow control operator '%s' is not set correctly!\n", wf->tasks[k].name);
		return OPH_WORKFLOW_EXIT_BAD_PARAM_ERROR;
	}

	return OPH_WORKFLOW_EXIT_SUCCESS;
}
int oph_workflow_validate(oph_workflow * workflow)
{
	if (!workflow || !(workflow->tasks)) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Null param\n");
		return OPH_WORKFLOW_EXIT_BAD_PARAM_ERROR;
	}
	// Check for uniqueness of task name
	int i, j, k;
	for (i = 0; i < workflow->tasks_num; i++)
		for (j = 0; j < workflow->tasks_num; j++)
			if ((i != j) && !strcmp(workflow->tasks[i].name, workflow->tasks[j].name))
				return OPH_WORKFLOW_EXIT_TASK_NAME_ERROR;

	// Create graph from tasks
	workflow_node *graph = NULL;
	graph = (workflow_node *) calloc(workflow->tasks_num, sizeof(workflow_node));
	if (!graph) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating graph\n");
		return OPH_WORKFLOW_EXIT_MEMORY_ERROR;
	}

	for (i = 0; i < workflow->tasks_num; i++) {
		if (workflow->tasks[i].deps_num >= 1) {
			graph[i].in_edges = (int *) calloc(workflow->tasks[i].deps_num, sizeof(int));
			if (!(graph[i].in_edges)) {
				for (k = 0; k < workflow->tasks_num; k++)
					workflow_node_free(&(graph[k]));
				free(graph);
				graph = NULL;
				pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating in_edges\n");
				return OPH_WORKFLOW_EXIT_MEMORY_ERROR;
			}
			graph[i].in_edges_size = workflow->tasks[i].deps_num;
			graph[i].in_edges_num = workflow->tasks[i].deps_num;
			for (j = 0; j < workflow->tasks[i].deps_num; j++)
				graph[i].in_edges[j] = workflow->tasks[i].deps[j].task_index;
		}
		if (workflow->tasks[i].dependents_indexes_num >= 1) {
			graph[i].out_edges = (int *) calloc(workflow->tasks[i].dependents_indexes_num, sizeof(int));
			if (!(graph[i].out_edges)) {
				for (k = 0; k < workflow->tasks_num; k++)
					workflow_node_free(&(graph[k]));
				free(graph);
				graph = NULL;
				pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating out_edges\n");
				return OPH_WORKFLOW_EXIT_MEMORY_ERROR;
			}
			graph[i].out_edges_size = workflow->tasks[i].dependents_indexes_num;
			graph[i].out_edges_num = workflow->tasks[i].dependents_indexes_num;
			for (j = 0; j < workflow->tasks[i].dependents_indexes_num; j++)
				graph[i].out_edges[j] = workflow->tasks[i].dependents_indexes[j];
		}
		graph[i].index = i;
	}

	/*  Test for DAG through Topological Sort
	 *
	 *      S ← Set of all nodes with no incoming edges
	 *      while S is non-empty do
	 *          remove a node n from S
	 *          for each node m with an edge e from n to m do
	 *              remove edge e from the graph
	 *              if m has no other incoming edges then
	 *                  insert m into S
	 *      if graph has edges then
	 *          return error (graph has at least one cycle)
	 *      else
	 *          return success (graph has no cycles)
	 */

	//      S ← Set of all nodes with no incoming edges
	workflow_s_nodes S;
	S.head = NULL;
	S.tail = NULL;
	S.nodes_num = 0;
	for (i = 0; i < workflow->tasks_num; i++) {
		if (graph[i].in_edges_num == 0) {
			if (workflow_s_add(&S, &(graph[i]))) {
				for (k = 0; k < workflow->tasks_num; k++)
					workflow_node_free(&(graph[k]));
				free(graph);
				graph = NULL;
				workflow_s_nodes_free(&S);
				pmesg(LOG_ERROR, __FILE__, __LINE__, "Error setting S\n");
				return OPH_WORKFLOW_EXIT_MEMORY_ERROR;
			}
		}
	}

	workflow_node *n = NULL;

	//      while S is non-empty do
	while (S.nodes_num != 0) {
		//          remove a node n from S
		if (workflow_s_remove(&S, &n)) {
			for (k = 0; k < workflow->tasks_num; k++)
				workflow_node_free(&(graph[k]));
			free(graph);
			graph = NULL;
			workflow_s_nodes_free(&S);
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Error removing node from S\n");
			return OPH_WORKFLOW_EXIT_MEMORY_ERROR;
		}
		//          for each node m with an edge e from n to m do
		for (i = 0; i < n->out_edges_size; i++) {
			if (n->out_edges[i] != -1) {
				//              remove edge e from the graph
				int index = n->out_edges[i];
				n->out_edges[i] = -1;
				n->out_edges_num--;
				for (j = 0; j < graph[index].in_edges_size; j++) {
					if (graph[index].in_edges[j] == n->index) {
						graph[index].in_edges[j] = -1;
						graph[index].in_edges_num--;
						//              if m has no other incoming edges then
						if (graph[index].in_edges_num == 0) {
							//                  insert m into S
							if (workflow_s_add(&S, &(graph[index]))) {
								for (k = 0; k < workflow->tasks_num; k++)
									workflow_node_free(&(graph[k]));
								free(graph);
								graph = NULL;
								workflow_s_nodes_free(&S);
								pmesg(LOG_ERROR, __FILE__, __LINE__, "Error adding a node to S\n");
								return OPH_WORKFLOW_EXIT_GENERIC_ERROR;
							}
						}
						break;
					}
				}
			}
		}
	}

	for (i = 0; i < workflow->tasks_num; i++) {
		//      if graph has edges then
		if (graph[i].in_edges_num != 0 || graph[i].out_edges_num != 0) {
			for (k = 0; k < workflow->tasks_num; k++)
				workflow_node_free(&(graph[k]));
			free(graph);
			graph = NULL;
			workflow_s_nodes_free(&S);
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Graph is not a DAG!\n");
			//          return error (graph has at least one cycle)
			return OPH_WORKFLOW_EXIT_BAD_PARAM_ERROR;
		}
	}

	for (k = 0; k < workflow->tasks_num; k++)
		workflow_node_free(&(graph[k]));
	free(graph);
	graph = NULL;
	workflow_s_nodes_free(&S);

	// Check for flow control operators
	if (workflow_validate_fco(workflow))
		return OPH_WORKFLOW_EXIT_FLOW_CONTROL_ERROR;

	return OPH_WORKFLOW_EXIT_SUCCESS;
}
char* oph_gsl_spline(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error)
{
	if (*error)
	{
	        *length=0;
	        *is_null=0;
	        *error=1;
	        return NULL;
	}
	if (*is_null || !args->lengths[2] || !args->lengths[3] || !args->lengths[4])
	{
	        *length=0;
	        *is_null=1;
	        *error=0;
	        return NULL;
	}

	oph_generic_param_multi* param;
	if (!initid->ptr)
	{
		param = (oph_generic_param_multi*)malloc(sizeof(oph_generic_param_multi));
		if (!param)
		{
			pmesg(1, __FILE__, __LINE__, "Error in allocating parameters\n");
			*length=0;
			*is_null=0;
			*error=1;
			return NULL;
		}
		param->measure = NULL;
		param->result = NULL;
		param->error = 0;
		param->extend = NULL;

		initid->ptr = (char*)param;
	}
	else param = (oph_generic_param_multi*)initid->ptr;

	if (param->error)
	{
		*length=0;
		*is_null=0;
		*error=1;
		return NULL;
	}

	oph_multistring* measure;
	if (!param->error && !param->measure)
	{
		if(core_set_oph_multistring(&measure, args->args[0], &(args->lengths[0])))
		{
			param->error = 1;
			pmesg(1, __FILE__, __LINE__, "Error setting measure structure\n");
			*length=0;
			*is_null=0;
			*error=1;
			return NULL;
		}
		if (!measure->islast)
		{
			param->error = 1;
			pmesg(1, __FILE__, __LINE__, "Wrong number of input data type\n");
			*length=0;
			*is_null=0;
			*error=1;
			return NULL;
		}
		measure->length = args->lengths[2];
		if(measure->length % measure->blocksize)
		{
			param->error = 1;
			pmesg(1, __FILE__, __LINE__, "Wrong input type or data corrupted\n");
			*length=0;
			*is_null=0;
			*error=1;
			return NULL;
		}
		measure->numelem = measure->length / measure->blocksize;
		if (measure->numelem*sizeof(double) != args->lengths[3])
		{
			param->error = 1;
			pmesg(1, __FILE__, __LINE__, "Wrong input type or data corrupted\n");
			*length=0;
			*is_null=0;
			*error=1;
			return NULL;
		}

		param->measure = measure;
	}
	else measure = param->measure;

	measure->content = args->args[2];

	oph_multistring* output;
	if (!param->error && !param->result)
	{
		if(core_set_oph_multistring(&output, args->args[1], &(args->lengths[1])))
		{
			param->error = 1;
			pmesg(1, __FILE__, __LINE__, "Error setting measure structure\n");
			*length=0;
			*is_null=0;
			*error=1;
			return NULL;
		}
		if (output->num_measure == measure->num_measure)
		{
			output->length = args->lengths[4];
			if(output->length % sizeof(double))
			{
				param->error = 1;
				pmesg(1, __FILE__, __LINE__, "Wrong input type or data corrupted\n");
				*length=0;
				*is_null=0;
				*error=1;
				return NULL;
			}
			output->numelem = output->length / sizeof(double);
			output->length = output->numelem * output->blocksize;
		}
		else
		{
			param->error = 1;
			pmesg(1, __FILE__, __LINE__, "Wrong number of output data type\n");
			*length=0;
			*is_null=0;
			*error=1;
			return NULL;
		}
		if(!output->length)
		{
			*length=0;
			*is_null=1;
			*error=0;
			return NULL;
		}
		output->content = (char *)malloc(output->length);
		if(!output->content)
		{
			param->error = 1;
			pmesg(1,  __FILE__, __LINE__, "Error allocating measures string\n");
			*length=0;
			*is_null=0;
			*error=1;
			return NULL;
		}

		param->result = output;
	}
	else output = param->result;

	oph_gsl_spline_param* spline;
	if (!param->extend)
	{
		spline = (oph_gsl_spline_param*)malloc(sizeof(oph_gsl_spline_param));
		spline->acc = gsl_interp_accel_alloc();
		if (!spline->acc)
		{
			param->error = 1;
			pmesg(1,  __FILE__, __LINE__, "Unable to compute result\n");
			*length=0;
			*is_null=0;
			*error=1;
			return NULL;
		}
		spline->spline = gsl_spline_alloc(gsl_interp_cspline, measure->numelem);
		if (!spline->spline)
		{
			param->error = 1;
			pmesg(1,  __FILE__, __LINE__, "Unable to compute result\n");
			*length=0;
			*is_null=0;
			*error=1;
			return NULL;
		}
		spline->tmp = (double*)malloc(measure->numelem * sizeof(double)); // Intermediate position of input arrays
		if (!spline->tmp)
		{
			param->error = 1;
			pmesg(1,  __FILE__, __LINE__, "Unable to compute result\n");
			*length=0;
			*is_null=0;
			*error=1;
			return NULL;
		}
		param->extend = (void*)spline;
	}
	else spline = (oph_gsl_spline_param*)param->extend;

	spline->old_x = (double*)args->args[3];
	spline->new_x = (double*)args->args[4];

	if(!param->error && core_oph_gsl_spline_multi(param->measure,param->result,spline))
	{
		param->error = 1;
		pmesg(1,  __FILE__, __LINE__, "Unable to compute result\n");
		*length=0;
		*is_null=0;
		*error=1;
		return NULL;
        }

	*length=output->length;
        *error=0;
        *is_null=0;

        return (result = output->content);
}
int oph_subset_parse(const char *cond, unsigned long len, oph_subset * subset, long max)
{
	char *result, *result2, temp0[OPH_SUBSET_LIB_MAX_STRING_LENGTH], temp1[OPH_SUBSET_LIB_MAX_STRING_LENGTH], temp2[OPH_SUBSET_LIB_MAX_STRING_LENGTH], *next, *temp, *savepointer = NULL;
	unsigned int number;

	if (!subset) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Null pointer\n");
		return OPH_SUBSET_LIB_NULL_POINTER_ERR;
	}

	subset->number = 0;
	strncpy(temp0, cond, len);
	temp0[len] = '\0';

	strcpy(temp2, temp0);
	result = strtok_r(temp0, OPH_SUBSET_LIB_SUBSET_SEPARATOR, &savepointer);

	while (result) {
		subset->number++;
		result = strtok_r(NULL, OPH_SUBSET_LIB_SUBSET_SEPARATOR, &savepointer);
	}

	if (!subset->number)
		return OPH_SUBSET_LIB_DATA_ERR;

	int retval = OPH_SUBSET_LIB_OK, i = 0;

	subset->type = (oph_subset_type *) malloc(subset->number * sizeof(oph_subset_type));
	subset->start = (long *) malloc(subset->number * sizeof(long));
	subset->end = (long *) malloc(subset->number * sizeof(long));
	subset->stride = (unsigned long *) malloc(subset->number * sizeof(unsigned long));
	subset->count = (unsigned long *) malloc(subset->number * sizeof(unsigned long));
	subset->total = 0;

	next = temp2;
	result = strchr(temp2, OPH_SUBSET_LIB_SUBSET_SEPARATOR[0]);

	while (next && (retval == OPH_SUBSET_LIB_OK)) {
		if (result) {
			result[0] = '\0';
			temp = result + 1;
		} else
			temp = 0;
		result = next;
		next = temp;

		number = 0;
		strncpy(temp1, result, OPH_SUBSET_LIB_MAX_STRING_LENGTH);
		result2 = strtok_r(temp1, OPH_SUBSET_LIB_PARAM_SEPARATOR, &savepointer);
		while (result2 && (retval == OPH_SUBSET_LIB_OK)) {
			switch (number) {
				case 0:
					if (!strncasecmp(result2, OPH_SUBSET_LIB_PARAM_END, strlen(OPH_SUBSET_LIB_PARAM_END))) {
						if (max)
							subset->end[i] = max;
						else {
							pmesg(LOG_ERROR, __FILE__, __LINE__, "Clause '%s' cannot be used in this context\n", OPH_SUBSET_LIB_PARAM_END);
							retval = OPH_SUBSET_LIB_DATA_ERR;
						}
					} else
						subset->end[i] = strtol(result2, NULL, 10);
					subset->start[i] = subset->end[i];
					subset->stride[i] = 1;
					subset->type[i] = OPH_SUBSET_LIB_SINGLE;
					break;
				case 1:
					if (!strncasecmp(result2, OPH_SUBSET_LIB_PARAM_END, strlen(OPH_SUBSET_LIB_PARAM_END))) {
						if (max)
							subset->end[i] = max;
						else {
							pmesg(LOG_ERROR, __FILE__, __LINE__, "Clause '%s' cannot be used in this context\n", OPH_SUBSET_LIB_PARAM_END);
							retval = OPH_SUBSET_LIB_DATA_ERR;
						}
					} else
						subset->end[i] = strtol(result2, NULL, 10);
					subset->type[i] = OPH_SUBSET_LIB_INTERVAL;
					break;
				case 2:
					subset->stride[i] = subset->end[i];
					if (!strncasecmp(result2, OPH_SUBSET_LIB_PARAM_END, strlen(OPH_SUBSET_LIB_PARAM_END))) {
						if (max)
							subset->end[i] = max;
						else {
							pmesg(LOG_ERROR, __FILE__, __LINE__, "Clause '%s' cannot be used in this context\n", OPH_SUBSET_LIB_PARAM_END);
							retval = OPH_SUBSET_LIB_DATA_ERR;
						}
					} else
						subset->end[i] = strtol(result2, NULL, 10);
					if (subset->stride[i] > 1)
						subset->type[i] = OPH_SUBSET_LIB_STRIDE;
					break;
				default:
					pmesg(LOG_ERROR, __FILE__, __LINE__, "Wrong input data: too many '%s' in subset\n", OPH_SUBSET_LIB_PARAM_SEPARATOR);
					retval = OPH_SUBSET_LIB_DATA_ERR;
			}
			number++;
			result2 = strtok_r(NULL, OPH_SUBSET_LIB_PARAM_SEPARATOR, &savepointer);
		}
		if (retval != OPH_SUBSET_LIB_OK)
			break;

		if (!number) {
			subset->type[i] = OPH_SUBSET_LIB_INTERVAL;
			subset->start[i] = subset->stride[i] = 1;
			if (max)
				subset->end[i] = max;
			else
				subset->end[i] = subset->start[i];
		}

		if (!subset->stride[i] || (subset->start[i] > subset->end[i])) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Wrong input data: 'start', 'stop' or 'step' parameters are not correctly set\n");
			retval = OPH_SUBSET_LIB_DATA_ERR;
			break;
		}
		subset->count[i] = 1 + (subset->end[i] - subset->start[i]) / subset->stride[i];
		subset->total += subset->count[i];
		++i;
		if (next)
			result = strchr(next, OPH_SUBSET_LIB_SUBSET_SEPARATOR[0]);
	}

	if (retval != OPH_SUBSET_LIB_OK)
		_oph_subset_free(subset);

	return retval;
}
int task_execute(oph_operator_struct * handle)
{
	if (!handle || !handle->operator_handle) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Null Handle\n");
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_NULL_OPERATOR_HANDLE);
		return OPH_ANALYTICS_OPERATOR_NULL_OPERATOR_HANDLE;
	}
	//Only master process has to continue
	if (handle->proc_rank != 0)
		return OPH_ANALYTICS_OPERATOR_SUCCESS;

	logging(LOG_INFO, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_INFO_START);

	int level = ((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->level;
	char *func_ret = ((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->func_ret;
	char *func_type = ((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->func_type;
	char *name_filter = ((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->name_filter;
	int limit = ((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->limit;
	int id_dbms = ((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->id_dbms;
	ophidiadb *oDB = &((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->oDB;
	char **objkeys = ((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->objkeys;
	int objkeys_num = ((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->objkeys_num;

	if (oph_odb_read_ophidiadb_config_file(oDB)) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to read OphidiaDB configuration\n");
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_OPHIDIADB_CONFIGURATION_FILE_NO_CONTAINER);
		return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
	}

	if (oph_odb_connect_to_ophidiadb(oDB)) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to connect to OphidiaDB. Check access parameters.\n");
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_OPHIDIADB_CONNECTION_ERROR_NO_CONTAINER);
		oph_odb_disconnect_from_ophidiadb(&((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->oDB);
		return OPH_ANALYTICS_OPERATOR_MYSQL_ERROR;
	}

	oph_odb_dbms_instance dbms;
	if (id_dbms == 0) {
		if (oph_odb_stge_retrieve_first_dbmsinstance(oDB, &dbms)) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to retrieve DBMS info\n");
			logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_RETRIEVE_DBMS_ERROR, id_dbms);
			oph_odb_disconnect_from_ophidiadb(&((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->oDB);
			return OPH_ANALYTICS_OPERATOR_MYSQL_ERROR;
		}
	} else {
		if (oph_odb_stge_retrieve_dbmsinstance(oDB, id_dbms, &dbms)) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to retrieve DBMS info\n");
			logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_RETRIEVE_DBMS_ERROR, id_dbms);
			oph_odb_disconnect_from_ophidiadb(&((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->oDB);
			return OPH_ANALYTICS_OPERATOR_MYSQL_ERROR;
		}
	}
	oph_odb_disconnect_from_ophidiadb(&((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->oDB);

	int num_fields;
	switch (level) {
		case 5:
			printf("+-------------------------------------+--------------+-----------------------------------------------+-----------------+---------+\n");
			printf("| %-35s | %-12s | %-45s | %-15s | %-7s |\n", "PRIMITIVE NAME", "RETURN TYPE", "DYNAMIC LIBRARY", "PRIMITIVE TYPE", "DBMS ID");
			printf("+-------------------------------------+--------------+-----------------------------------------------+-----------------+---------+\n");
			if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST)) {
				num_fields = 5;
				char *keys[5] = { "PRIMITIVE NAME", "RETURN TYPE", "DYNAMIC LIBRARY", "PRIMITIVE TYPE", "DBMS ID" };
				char *fieldtypes[5] = { "string", "string", "string", "string", "int" };
				if (oph_json_add_grid(handle->operator_json, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST, "Primitives List", NULL, keys, num_fields, fieldtypes, num_fields)) {
					pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRID error\n");
					logging(LOG_WARNING, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "ADD GRID error\n");
					return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
				}
			}
			break;
		case 4:
			printf("+-------------------------------------+--------------+-----------------------------------------------+-----------------+\n");
			printf("| %-35s | %-12s | %-45s | %-15s |\n", "PRIMITIVE NAME", "RETURN TYPE", "DYNAMIC LIBRARY", "PRIMITIVE TYPE");
			printf("+-------------------------------------+--------------+-----------------------------------------------+-----------------+\n");
			if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST)) {
				num_fields = 4;
				char *keys[4] = { "PRIMITIVE NAME", "RETURN TYPE", "DYNAMIC LIBRARY", "PRIMITIVE TYPE" };
				char *fieldtypes[4] = { "string", "string", "string", "string" };
				if (oph_json_add_grid(handle->operator_json, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST, "Primitives List", NULL, keys, num_fields, fieldtypes, num_fields)) {
					pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRID error\n");
					logging(LOG_WARNING, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "ADD GRID error\n");
					return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
				}
			}
			break;
		case 3:
			printf("+-------------------------------------+--------------+-----------------------------------------------+\n");
			printf("| %-35s | %-12s | %-45s |\n", "PRIMITIVE NAME", "RETURN TYPE", "DYNAMIC LIBRARY");
			printf("+-------------------------------------+--------------+-----------------------------------------------+\n");
			if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST)) {
				num_fields = 3;
				char *keys[3] = { "PRIMITIVE NAME", "RETURN TYPE", "DYNAMIC LIBRARY" };
				char *fieldtypes[3] = { "string", "string", "string" };
				if (oph_json_add_grid(handle->operator_json, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST, "Primitives List", NULL, keys, num_fields, fieldtypes, num_fields)) {
					pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRID error\n");
					logging(LOG_WARNING, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "ADD GRID error\n");
					return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
				}
			}
			break;
		case 2:
			printf("+-------------------------------------+--------------+\n");
			printf("| %-35s | %-12s |\n", "PRIMITIVE NAME", "RETURN TYPE");
			printf("+-------------------------------------+--------------+\n");
			if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST)) {
				num_fields = 2;
				char *keys[2] = { "PRIMITIVE NAME", "RETURN TYPE" };
				char *fieldtypes[2] = { "string", "string" };
				if (oph_json_add_grid(handle->operator_json, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST, "Primitives List", NULL, keys, num_fields, fieldtypes, num_fields)) {
					pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRID error\n");
					logging(LOG_WARNING, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "ADD GRID error\n");
					return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
				}
			}
			break;
		case 1:
			printf("+-------------------------------------+\n");
			printf("| %-35s |\n", "PRIMITIVE NAME");
			printf("+-------------------------------------+\n");
			if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST)) {
				num_fields = 1;
				char *keys[1] = { "PRIMITIVE NAME" };
				char *fieldtypes[1] = { "string" };
				if (oph_json_add_grid(handle->operator_json, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST, "Primitives List", NULL, keys, num_fields, fieldtypes, num_fields)) {
					pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRID error\n");
					logging(LOG_WARNING, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "ADD GRID error\n");
					return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
				}
			}
			break;
		default:
			pmesg(LOG_ERROR, __FILE__, __LINE__, "List level unrecognized\n");
			logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_BAD_LEVEL);
			return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
	}

	if (oph_dc_setup_dbms(&(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server), dbms.io_server_type)) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to initialize IO server.\n");
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_IOPLUGIN_SETUP_ERROR, dbms.io_server_type);
		return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
	}

	if (oph_dc_connect_to_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, &dbms, 0)) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to connect to DBMS. Check access parameters.\n");
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_CONNECT_DBMS_ERROR, dbms.id_dbms);
		oph_dc_disconnect_from_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, &dbms);
		oph_dc_cleanup_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server);
		return OPH_ANALYTICS_OPERATOR_MYSQL_ERROR;
	}

	oph_ioserver_result *primitives_list = NULL;

	//retrieve primitives list
	if (oph_dc_get_primitives(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, &dbms, name_filter, &primitives_list)) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to retrieve primitives list\n");
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_RETRIEVE_LIST_ERROR, dbms.id_dbms);
		oph_dc_disconnect_from_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, &dbms);
		oph_dc_cleanup_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server);
		return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
	}

	int num_rows = 0;

	//Empty set
	if (!(num_rows = primitives_list->num_rows)) {
		pmesg(LOG_WARNING, __FILE__, __LINE__, "No rows found by query\n");
		logging(LOG_WARNING, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_NO_ROWS_FOUND);
		oph_ioserver_free_result(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, primitives_list);
		oph_dc_disconnect_from_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, &dbms);
		oph_dc_cleanup_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server);
		return OPH_ANALYTICS_OPERATOR_SUCCESS;
	}

	if (primitives_list->num_fields != 4) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Not enough fields found by query\n");
		logging(LOG_WARNING, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_NO_ROWS_FOUND);
		oph_ioserver_free_result(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, primitives_list);
		oph_dc_disconnect_from_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, &dbms);
		oph_dc_cleanup_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server);
		return OPH_ANALYTICS_OPERATOR_SUCCESS;
	}

	oph_ioserver_row *curr_row = NULL;

	if (oph_ioserver_fetch_row(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, primitives_list, &curr_row)) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to fetch row\n");
		logging(LOG_WARNING, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_ROW_ERROR);
		oph_ioserver_free_result(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, primitives_list);
		oph_dc_disconnect_from_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, &dbms);
		oph_dc_cleanup_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server);
		return OPH_DC_SERVER_ERROR;
	}
	//For each ROW
	char tmp_ret[OPH_COMMON_BUFFER_LEN] = { '\0' }, tmp_type[OPH_COMMON_BUFFER_LEN] = {
	'\0'};
	int n;
	int count_limit = 0;
	while (curr_row->row) {
		if (limit > 0 && count_limit >= limit)
			break;
		switch (level) {
			case 5:
				if (func_ret || func_type) {
					if (func_ret) {
						n = snprintf(tmp_ret, OPH_COMMON_BUFFER_LEN, "%s", (curr_row->row[1][0] == '0') ? "array" : "number");
						if (n <= 0)
							break;
						if (strncmp(tmp_ret, func_ret, OPH_COMMON_BUFFER_LEN) != 0)
							break;
					}
					if (func_type) {
						n = snprintf(tmp_type, OPH_COMMON_BUFFER_LEN, "%s", (curr_row->row[3][0] == 'f') ? "simple" : "aggregate");
						if (n <= 0)
							break;
						if (strncmp(tmp_type, func_type, OPH_COMMON_BUFFER_LEN) != 0)
							break;
					}
					printf("| %-35s | %-12s | %-45s | %-15s | %7d |\n", curr_row->row[0], (curr_row->row[1][0] == '0') ? "array" : "number", curr_row->row[2],
					       (curr_row->row[3][0] == 'f') ? "simple" : "aggregate", dbms.id_dbms);
					if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST)) {
						char tmpbuf[20];
						snprintf(tmpbuf, 20, "%d", dbms.id_dbms);
						char *my_row[5] =
						    { curr_row->row[0], (curr_row->row[1][0] == '0') ? "array" : "number", curr_row->row[2], (curr_row->row[3][0] == 'f') ? "simple" : "aggregate",
							tmpbuf
						};
						if (oph_json_add_grid_row(handle->operator_json, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST, my_row)) {
							pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRID ROW error\n");
							logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "ADD GRID ROW error\n");
							oph_ioserver_free_result(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, primitives_list);
							oph_dc_disconnect_from_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, &dbms);
							oph_dc_cleanup_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server);
							return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
						}
					}
				} else {
					printf("| %-35s | %-12s | %-45s | %-15s | %7d |\n", curr_row->row[0], (curr_row->row[1][0] == '0') ? "array" : "number", curr_row->row[2],
					       (curr_row->row[3][0] == 'f') ? "simple" : "aggregate", dbms.id_dbms);
					if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST)) {
						char tmpbuf[20];
						snprintf(tmpbuf, 20, "%d", dbms.id_dbms);
						char *my_row[5] =
						    { curr_row->row[0], (curr_row->row[1][0] == '0') ? "array" : "number", curr_row->row[2], (curr_row->row[3][0] == 'f') ? "simple" : "aggregate",
							tmpbuf
						};
						if (oph_json_add_grid_row(handle->operator_json, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST, my_row)) {
							pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRID ROW error\n");
							logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "ADD GRID ROW error\n");
							oph_ioserver_free_result(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, primitives_list);
							oph_dc_disconnect_from_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, &dbms);
							oph_dc_cleanup_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server);
							return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
						}
					}
				}
				count_limit++;
				break;
			case 4:
				if (func_ret || func_type) {
					if (func_ret) {
						n = snprintf(tmp_ret, OPH_COMMON_BUFFER_LEN, "%s", (curr_row->row[1][0] == '0') ? "array" : "number");
						if (n <= 0)
							break;
						if (strncmp(tmp_ret, func_ret, OPH_COMMON_BUFFER_LEN) != 0)
							break;
					}
					if (func_type) {
						n = snprintf(tmp_type, OPH_COMMON_BUFFER_LEN, "%s", (curr_row->row[3][0] == 'f') ? "simple" : "aggregate");
						if (n <= 0)
							break;
						if (strncmp(tmp_type, func_type, OPH_COMMON_BUFFER_LEN) != 0)
							break;
					}
					printf("| %-35s | %-12s | %-45s | %-15s |\n", curr_row->row[0], (curr_row->row[1][0] == '0') ? "array" : "number", curr_row->row[2],
					       (curr_row->row[3][0] == 'f') ? "simple" : "aggregate");
					if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST)) {
						char *my_row[4] =
						    { curr_row->row[0], (curr_row->row[1][0] == '0') ? "array" : "number", curr_row->row[2], (curr_row->row[3][0] == 'f') ? "simple" : "aggregate" };
						if (oph_json_add_grid_row(handle->operator_json, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST, my_row)) {
							pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRID ROW error\n");
							logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "ADD GRID ROW error\n");
							oph_ioserver_free_result(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, primitives_list);
							oph_dc_disconnect_from_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, &dbms);
							oph_dc_cleanup_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server);
							return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
						}
					}
				} else {
					printf("| %-35s | %-12s | %-45s | %-15s |\n", curr_row->row[0], (curr_row->row[1][0] == '0') ? "array" : "number", curr_row->row[2],
					       (curr_row->row[3][0] == 'f') ? "simple" : "aggregate");
					if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST)) {
						char *my_row[4] =
						    { curr_row->row[0], (curr_row->row[1][0] == '0') ? "array" : "number", curr_row->row[2], (curr_row->row[3][0] == 'f') ? "simple" : "aggregate" };
						if (oph_json_add_grid_row(handle->operator_json, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST, my_row)) {
							pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRID ROW error\n");
							logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "ADD GRID ROW error\n");
							oph_ioserver_free_result(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, primitives_list);
							oph_dc_disconnect_from_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, &dbms);
							oph_dc_cleanup_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server);
							return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
						}
					}
				}
				count_limit++;
				break;
			case 3:
				if (func_ret) {
					n = snprintf(tmp_ret, OPH_COMMON_BUFFER_LEN, "%s", (curr_row->row[1][0] == '0') ? "array" : "number");
					if (n <= 0)
						break;
					if (strncmp(tmp_ret, func_ret, OPH_COMMON_BUFFER_LEN) != 0)
						break;
					printf("| %-35s | %-12s | %-45s |\n", curr_row->row[0], (curr_row->row[1][0] == '0') ? "array" : "number", curr_row->row[2]);
					if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST)) {
						char *my_row[3] = { curr_row->row[0], (curr_row->row[1][0] == '0') ? "array" : "number", curr_row->row[2] };
						if (oph_json_add_grid_row(handle->operator_json, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST, my_row)) {
							pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRID ROW error\n");
							logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "ADD GRID ROW error\n");
							oph_ioserver_free_result(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, primitives_list);
							oph_dc_disconnect_from_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, &dbms);
							oph_dc_cleanup_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server);
							return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
						}
					}
				} else {
					printf("| %-35s | %-12s | %-45s |\n", curr_row->row[0], (curr_row->row[1][0] == '0') ? "array" : "number", curr_row->row[2]);
					if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST)) {
						char *my_row[3] = { curr_row->row[0], (curr_row->row[1][0] == '0') ? "array" : "number", curr_row->row[2] };
						if (oph_json_add_grid_row(handle->operator_json, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST, my_row)) {
							pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRID ROW error\n");
							logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "ADD GRID ROW error\n");
							oph_ioserver_free_result(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, primitives_list);
							oph_dc_disconnect_from_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, &dbms);
							oph_dc_cleanup_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server);
							return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
						}
					}
				}
				count_limit++;
				break;
			case 2:
				if (func_ret) {
					n = snprintf(tmp_ret, OPH_COMMON_BUFFER_LEN, "%s", (curr_row->row[1][0] == '0') ? "array" : "number");
					if (n <= 0)
						break;
					if (strncmp(tmp_ret, func_ret, OPH_COMMON_BUFFER_LEN) != 0)
						break;
					printf("| %-35s | %-12s |\n", curr_row->row[0], (curr_row->row[1][0] == '0') ? "array" : "number");
					if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST)) {
						char *my_row[2] = { curr_row->row[0], (curr_row->row[1][0] == '0') ? "array" : "number" };
						if (oph_json_add_grid_row(handle->operator_json, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST, my_row)) {
							pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRID ROW error\n");
							logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "ADD GRID ROW error\n");
							oph_ioserver_free_result(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, primitives_list);
							oph_dc_disconnect_from_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, &dbms);
							oph_dc_cleanup_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server);
							return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
						}
					}
				} else {
					printf("| %-35s | %-12s |\n", curr_row->row[0], (curr_row->row[1][0] == '0') ? "array" : "number");
					if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST)) {
						char *my_row[2] = { curr_row->row[0], (curr_row->row[1][0] == '0') ? "array" : "number" };
						if (oph_json_add_grid_row(handle->operator_json, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST, my_row)) {
							pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRID ROW error\n");
							logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "ADD GRID ROW error\n");
							oph_ioserver_free_result(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, primitives_list);
							oph_dc_disconnect_from_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, &dbms);
							oph_dc_cleanup_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server);
							return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
						}
					}
				}
				count_limit++;
				break;
			case 1:
				printf("| %-35s |\n", curr_row->row[0]);
				if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST)) {
					char *my_row[1] = { curr_row->row[0] };
					if (oph_json_add_grid_row(handle->operator_json, OPH_JSON_OBJKEY_PRIMITIVES_LIST_LIST, my_row)) {
						pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRID ROW error\n");
						logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "ADD GRID ROW error\n");
						oph_ioserver_free_result(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, primitives_list);
						oph_dc_disconnect_from_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, &dbms);
						oph_dc_cleanup_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server);
						return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
					}
				}
				count_limit++;
				break;
			default:
				pmesg(LOG_ERROR, __FILE__, __LINE__, "List level unrecognized\n");
				logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_BAD_LEVEL);
				oph_ioserver_free_result(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, primitives_list);
				oph_dc_disconnect_from_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, &dbms);
				oph_dc_cleanup_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server);
				return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
		}

		if (oph_ioserver_fetch_row(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, primitives_list, &curr_row)) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to fetch row\n");
			logging(LOG_WARNING, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_ROW_ERROR);
			oph_ioserver_free_result(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, primitives_list);
			oph_dc_disconnect_from_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, &dbms);
			oph_dc_cleanup_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server);
			return OPH_DC_SERVER_ERROR;
		}

	}

	oph_ioserver_free_result(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, primitives_list);
	oph_dc_disconnect_from_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server, &dbms);
	oph_dc_cleanup_dbms(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server);

	switch (level) {
		case 5:
			printf("+-------------------------------------+--------------+-----------------------------------------------+-----------------+---------+\n");
			break;
		case 4:
			printf("+-------------------------------------+--------------+-----------------------------------------------+-----------------+\n");
			break;
		case 3:
			printf("+-------------------------------------+--------------+-----------------------------------------------+\n");
			break;
		case 2:
			printf("+-------------------------------------+--------------+\n");
			break;
		case 1:
			printf("+-------------------------------------+\n");
			break;
		default:
			pmesg(LOG_ERROR, __FILE__, __LINE__, "List level unrecognized\n");
			logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_BAD_LEVEL);
			return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
	}

	printf(OPH_PRIMITIVES_LIST_HELP_MESSAGE);
	if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_PRIMITIVES_LIST_TIP)) {
		if (oph_json_add_text(handle->operator_json, OPH_JSON_OBJKEY_PRIMITIVES_LIST_TIP, "Useful Tip", OPH_PRIMITIVES_LIST_HELP_MESSAGE)) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD TEXT error\n");
			logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "ADD TEXT error\n");
			return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
		}
	}

	logging(LOG_INFO, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_INFO_END);
	return OPH_ANALYTICS_OPERATOR_SUCCESS;
}
int task_execute(oph_operator_struct *handle)
{
  if (!handle || !handle->operator_handle){
  	pmesg(LOG_ERROR, __FILE__, __LINE__, "Null Handle\n");
	logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_DELETECONTAINER_NULL_OPERATOR_HANDLE );		
	  return OPH_ANALYTICS_OPERATOR_NULL_OPERATOR_HANDLE;
  }

  //Only master process has to continue
  if (handle->proc_rank != 0)
	return OPH_ANALYTICS_OPERATOR_SUCCESS;

  ophidiadb *oDB = &((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->oDB;
  int id_container = ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->id_input_container;
  int hidden = ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->hidden;
  int delete_type = ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->delete_type;
  char *container_name = ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->container_input;
  char *cwd = ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->cwd;
  char *user = ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->user;

  if(delete_type == OPH_DELETE_LOGIC_CODE) hidden = 0;

  //Check if user can operate on container and if container exists
  int permission = 0;
  int folder_id = 0;
  int container_exists = 0;
  //Check if input path exists
  if((oph_odb_fs_path_parsing("", cwd, &folder_id, NULL, oDB))) {
		//Check if user can work on datacube
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Path %s doesn't exists\n", cwd);
		logging(LOG_ERROR, __FILE__, __LINE__,  OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_DELETECONTAINER_CWD_ERROR, container_name, cwd );
		return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
  }
  if((oph_odb_fs_check_folder_session(folder_id, ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->sessionid, oDB, &permission)) || !permission){
		//Check if user can work on datacube
		pmesg(LOG_ERROR, __FILE__, __LINE__, "User %s is not allowed to work in this folder\n", user);
		logging(LOG_ERROR, __FILE__, __LINE__,  OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_DELETECONTAINER_DATACUBE_PERMISSION_ERROR, container_name, user );
		return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
  }
  if(oph_odb_fs_retrieve_container_id_from_container_name(oDB, folder_id, container_name, hidden, &id_container)){
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Unknown input %s container\n", (hidden ? "hidden" : "visible"));
		logging(LOG_ERROR, __FILE__, __LINE__,id_container, OPH_LOG_OPH_DELETECONTAINER_NO_INPUT_CONTAINER, (hidden ? "hidden" : "visible"), container_name  );
		return OPH_ANALYTICS_OPERATOR_MYSQL_ERROR;
  }
  ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->id_input_container = id_container;

  if(delete_type == OPH_DELETE_PHYSIC_CODE){
	  if(oph_odb_fs_check_if_container_empty(oDB, id_container)){
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Input container isn't empty\n");
		logging(LOG_ERROR, __FILE__, __LINE__, id_container, OPH_LOG_OPH_DELETECONTAINER_CONTAINER_NOT_EMPTY, container_name  );
		return OPH_ANALYTICS_OPERATOR_MYSQL_ERROR;
	  }

	  //Remove also grid related to container dimensions
	  if(oph_odb_dim_delete_from_grid_table(oDB, id_container)){
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Error while deleting grid related to container\n");
		logging(LOG_ERROR, __FILE__, __LINE__, ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->id_input_container, OPH_LOG_OPH_DELETECONTAINER_GRID_DELETE_ERROR );		
		return OPH_ANALYTICS_OPERATOR_MYSQL_ERROR;  
	  }

	  //Delete container and related dimensions/ dimension instances
	  if(oph_odb_fs_delete_from_container_table(oDB, id_container)){
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Error while deleting input container\n");
		logging(LOG_ERROR, __FILE__, __LINE__, ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->id_input_container, OPH_LOG_OPH_DELETECONTAINER_CONTAINER_DELETE_ERROR );		
		return OPH_ANALYTICS_OPERATOR_MYSQL_ERROR;  
	  }
 
	  oph_odb_db_instance db_;
	  oph_odb_db_instance *db = &db_;
	  if (oph_dim_load_dim_dbinstance(db))
	  {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Error while loading dimension db paramters\n");
		logging(LOG_ERROR, __FILE__, __LINE__, ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->id_input_container, OPH_LOG_OPH_DELETECONTAINER_DIM_LOAD );
		oph_dim_unload_dim_dbinstance(db);		
		return OPH_ANALYTICS_OPERATOR_MYSQL_ERROR; 
	  }
	  if (oph_dim_connect_to_dbms(db->dbms_instance, 0))
	  {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Error while connecting to dimension dbms\n");
		logging(LOG_ERROR, __FILE__, __LINE__, ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->id_input_container, OPH_LOG_OPH_DELETECONTAINER_DIM_CONNECT );
		oph_dim_disconnect_from_dbms(db->dbms_instance);
		oph_dim_unload_dim_dbinstance(db);
		return OPH_ANALYTICS_OPERATOR_MYSQL_ERROR; 
	  }
	  if (oph_dim_use_db_of_dbms(db->dbms_instance, db))
	  {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Error while opening dimension db\n");
		logging(LOG_ERROR, __FILE__, __LINE__, ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->id_input_container, OPH_LOG_OPH_DELETECONTAINER_DIM_USE_DB );
		oph_dim_disconnect_from_dbms(db->dbms_instance);
		oph_dim_unload_dim_dbinstance(db);
		return OPH_ANALYTICS_OPERATOR_MYSQL_ERROR; 
	  }

	  char index_dimension_table_name[OPH_COMMON_BUFFER_LEN],label_dimension_table_name[OPH_COMMON_BUFFER_LEN];
	  snprintf(index_dimension_table_name,OPH_COMMON_BUFFER_LEN,OPH_DIM_TABLE_NAME_MACRO,((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->id_input_container);
	  snprintf(label_dimension_table_name,OPH_COMMON_BUFFER_LEN,OPH_DIM_TABLE_LABEL_MACRO,((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->id_input_container);

	  if (oph_dim_delete_table(db, index_dimension_table_name))
	  {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Error while deleting dimension table\n");
		logging(LOG_ERROR, __FILE__, __LINE__, ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->id_input_container, OPH_LOG_OPH_DELETECONTAINER_DIM_TABLE_DELETE_ERROR );
		oph_dim_disconnect_from_dbms(db->dbms_instance);
		oph_dim_unload_dim_dbinstance(db);	
		return OPH_ANALYTICS_OPERATOR_MYSQL_ERROR; 
	  }
	  if (oph_dim_delete_table(db, label_dimension_table_name))
	  {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Error while deleting dimension table\n");
		logging(LOG_ERROR, __FILE__, __LINE__, ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->id_input_container, OPH_LOG_OPH_DELETECONTAINER_DIM_TABLE_DELETE_ERROR );
		oph_dim_disconnect_from_dbms(db->dbms_instance);
		oph_dim_unload_dim_dbinstance(db);	
		return OPH_ANALYTICS_OPERATOR_MYSQL_ERROR; 
	  }

	  oph_dim_disconnect_from_dbms(db->dbms_instance);
	  oph_dim_unload_dim_dbinstance(db);
  }
  else{
	//Check if hidden container exists in folder
	if(oph_odb_fs_is_hidden_container(folder_id, container_name,  oDB, &container_exists))
	{
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to check output container\n");
		logging(LOG_ERROR, __FILE__, __LINE__, id_container, OPH_LOG_OPH_DELETECONTAINER_OUTPUT_CONTAINER_ERROR_NO_CONTAINER, container_name, container_name );	
		return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
	}
	if (container_exists)
	{
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Hidden container '%s' already exists in this folder\n", container_name);
		logging(LOG_ERROR, __FILE__, __LINE__, id_container, OPH_LOG_OPH_DELETECONTAINER_OUTPUT_CONTAINER_EXIST_ERROR, container_name, container_name );
		return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
	}
	//If container exists then DELETE
	if(oph_odb_fs_set_container_hidden_status(id_container, 1, oDB)){
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to delete  logically  container %s\n", container_name);
		logging(LOG_ERROR, __FILE__, __LINE__, id_container, OPH_LOG_OPH_DELETECONTAINER_UPDATE_CONTAINER_ERROR, container_name );	
		return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
	}		
  }

  return OPH_ANALYTICS_OPERATOR_SUCCESS;
}
void *sum_array_r(void *initid_r)
{

	// Plugin thread function
	int thid;

	// Each thread has a subset of elements 
	unsigned long *th_array_dim = malloc(sizeof(unsigned long));

	for (thid = 0; thid < NTHREAD; thid++) {
		if (pthread_equal(((th_data *) (((UDF_INIT *) (initid_r))->extension))->thread[thid], pthread_self()))
			break;
	}
	for (;;) {
		barrier_wait(&(((th_data *) (((UDF_INIT *) (initid_r))->extension))->barr_start));
		if (((th_data *) (((UDF_INIT *) (initid_r))->extension))->exit_flag == 1)
			break;

		oph_string measurea;
		oph_string measureb;

		int res = 0;

		if (((UDF_ARGS *) ((th_data *) (((UDF_INIT *) (initid_r))->extension))->curr_args)->arg_count < 3) {
			core_set_type(&(measurea), NULL, 0);
			core_set_type(&(measureb), NULL, 0);
		} else if (((UDF_ARGS *) ((th_data *) (((UDF_INIT *) (initid_r))->extension))->curr_args)->arg_count == 3) {
			core_set_type(&(measurea), ((UDF_ARGS *) ((th_data *) (((UDF_INIT *) (initid_r))->extension))->curr_args)->args[2],
				      &(((UDF_ARGS *) ((th_data *) (((UDF_INIT *) (initid_r))->extension))->curr_args)->lengths[2]));
			core_set_type(&(measureb), NULL, 0);
		} else {
			core_set_type(&(measurea), ((UDF_ARGS *) ((th_data *) (((UDF_INIT *) (initid_r))->extension))->curr_args)->args[2],
				      &(((UDF_ARGS *) ((th_data *) (((UDF_INIT *) (initid_r))->extension))->curr_args)->lengths[2]));
			core_set_type(&(measureb), ((UDF_ARGS *) ((th_data *) (((UDF_INIT *) (initid_r))->extension))->curr_args)->args[3],
				      &(((UDF_ARGS *) ((th_data *) (((UDF_INIT *) (initid_r))->extension))->curr_args)->lengths[3]));
		}



		if (measurea.type != measureb.type) {
			pmesg(1, __FILE__, __LINE__, "Type are different; unable to sum values\n");
		}

		*th_array_dim = (((UDF_ARGS *) ((th_data *) (((UDF_INIT *) (initid_r))->extension))->curr_args)->lengths[0]) / NTHREAD;

		measurea.content = ((UDF_ARGS *) ((th_data *) (((UDF_INIT *) (initid_r))->extension))->curr_args)->args[0] + ((*th_array_dim) * thid);
		measurea.length = th_array_dim;
		measureb.content = ((UDF_ARGS *) ((th_data *) (((UDF_INIT *) (initid_r))->extension))->curr_args)->args[1] + ((*th_array_dim) * thid);
		measureb.length = th_array_dim;

		core_set_elemsize(&(measurea));

		if (core_set_numelem(&(measurea))) {
			pmesg(1, __FILE__, __LINE__, "Error on counting elements\n");
		}

		core_set_elemsize(&(measureb));

		if (core_set_numelem(&(measureb))) {
			pmesg(1, __FILE__, __LINE__, "Error on counting elements\n");
		}
		//Exit if array series have different number of elements
		if (measurea.numelem != measureb.numelem) {
			pmesg(1, __FILE__, __LINE__, "Number of array elements are different; unable to sum values\n");
		}


		res = core_oph_sum_array(&measurea, &measureb, (((UDF_INIT *) (initid_r))->ptr) + ((*th_array_dim) * thid));
		if (res) {
			pmesg(1, __FILE__, __LINE__, "Unable to compute result\n");
		}
		barrier_wait(&(((th_data *) (((UDF_INIT *) (initid_r))->extension))->barr_end));
	}			// end for
	free(th_array_dim);
	th_array_dim = NULL;
}
char *oph_gsl_complex_to_polar(UDF_INIT * initid, UDF_ARGS * args, char *result, unsigned long *length, char *is_null, char *error)
{
	if (*error) {
		*length = 0;
		*is_null = 0;
		*error = 1;
		return NULL;
	}
	if (*is_null || !args->lengths[2]) {
		*length = 0;
		*is_null = 1;
		*error = 0;
		return NULL;
	}

	if (!initid->ptr) {
		initid->ptr = (char *) calloc(1, sizeof(oph_string));
		if (!initid->ptr) {
			pmesg(1, __FILE__, __LINE__, "Error allocating result\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		oph_stringPtr output = (oph_stringPtr) initid->ptr;

		initid->extension = (char *) calloc(1, sizeof(oph_string));
		if (!initid->extension) {
			pmesg(1, __FILE__, __LINE__, "Error allocating measure\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		oph_stringPtr measure = (oph_stringPtr) initid->extension;

		core_set_type(measure, args->args[0], &(args->lengths[0]));
		if (measure->type != OPH_COMPLEX_INT && measure->type != OPH_COMPLEX_LONG && measure->type != OPH_COMPLEX_FLOAT && measure->type == OPH_COMPLEX_DOUBLE) {
			pmesg(1, __FILE__, __LINE__, "Invalid input type: complex required\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		measure->length = &(args->lengths[2]);

		if (core_set_elemsize(measure)) {
			pmesg(1, __FILE__, __LINE__, "Error on setting element size\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		if (core_set_numelem(measure)) {
			pmesg(1, __FILE__, __LINE__, "Error on counting result elements\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		core_set_type(output, args->args[1], &(args->lengths[1]));
		if (output->type != OPH_COMPLEX_INT && output->type != OPH_COMPLEX_LONG && output->type != OPH_COMPLEX_FLOAT && output->type != OPH_COMPLEX_DOUBLE) {
			pmesg(1, __FILE__, __LINE__, "Invalid output type: complex required\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		if (core_set_elemsize(output)) {
			pmesg(1, __FILE__, __LINE__, "Error on setting element size\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		output->length = (unsigned long *) calloc(1, sizeof(unsigned long));
		if (!output->length) {
			pmesg(1, __FILE__, __LINE__, "Error allocating length\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		*(output->length) = measure->numelem * output->elemsize;
		output->numelem = measure->numelem;

		output->content = (char *) calloc(1, *(output->length));
		if (!output->content) {
			pmesg(1, __FILE__, __LINE__, "Error allocating result string\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
	}

	oph_stringPtr output = (oph_stringPtr) initid->ptr;
	oph_stringPtr measure = (oph_stringPtr) initid->extension;
	measure->content = args->args[2];

	int i, j = 0;
	gsl_complex z;
	double val1, val2;
	switch (measure->type) {
		case OPH_COMPLEX_INT:
			switch (output->type) {
				case OPH_COMPLEX_INT:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((int *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((int *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(int)), OPH_DOUBLE, OPH_INT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(int)), OPH_DOUBLE, OPH_INT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_LONG:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((int *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((int *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(long long)), OPH_DOUBLE, OPH_LONG, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(long long)), OPH_DOUBLE, OPH_LONG, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_FLOAT:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((int *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((int *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(float)), OPH_DOUBLE, OPH_FLOAT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(float)), OPH_DOUBLE, OPH_FLOAT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_DOUBLE:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((int *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((int *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(double)), OPH_DOUBLE, OPH_DOUBLE, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(double)), OPH_DOUBLE, OPH_DOUBLE, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				default:
					pmesg(1, __FILE__, __LINE__, "Type not recognized\n");
					*length = 0;
					*is_null = 0;
					*error = 1;
					return NULL;
			}
			break;
		case OPH_COMPLEX_LONG:
			switch (output->type) {
				case OPH_COMPLEX_INT:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((long long *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((long long *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(int)), OPH_DOUBLE, OPH_INT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(int)), OPH_DOUBLE, OPH_INT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_LONG:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((long long *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((long long *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(long long)), OPH_DOUBLE, OPH_LONG, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(long long)), OPH_DOUBLE, OPH_LONG, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_FLOAT:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((long long *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((long long *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(float)), OPH_DOUBLE, OPH_FLOAT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(float)), OPH_DOUBLE, OPH_FLOAT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_DOUBLE:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((long long *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((long long *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(double)), OPH_DOUBLE, OPH_DOUBLE, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(double)), OPH_DOUBLE, OPH_DOUBLE, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				default:
					pmesg(1, __FILE__, __LINE__, "Type not recognized\n");
					*length = 0;
					*is_null = 0;
					*error = 1;
					return NULL;
			}
			break;
		case OPH_COMPLEX_FLOAT:
			switch (output->type) {
				case OPH_COMPLEX_INT:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((float *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((float *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(int)), OPH_DOUBLE, OPH_INT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(int)), OPH_DOUBLE, OPH_INT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_LONG:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((float *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((float *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(long long)), OPH_DOUBLE, OPH_LONG, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(long long)), OPH_DOUBLE, OPH_LONG, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_FLOAT:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((float *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((float *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(float)), OPH_DOUBLE, OPH_FLOAT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(float)), OPH_DOUBLE, OPH_FLOAT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_DOUBLE:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((float *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((float *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(double)), OPH_DOUBLE, OPH_DOUBLE, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(double)), OPH_DOUBLE, OPH_DOUBLE, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				default:
					pmesg(1, __FILE__, __LINE__, "Type not recognized\n");
					*length = 0;
					*is_null = 0;
					*error = 1;
					return NULL;
			}
			break;
		case OPH_COMPLEX_DOUBLE:
			switch (output->type) {
				case OPH_COMPLEX_INT:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = ((double *) (args->args[2]))[i];	//real part
						z.dat[1] = ((double *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(int)), OPH_DOUBLE, OPH_INT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(int)), OPH_DOUBLE, OPH_INT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_LONG:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = ((double *) (args->args[2]))[i];	//real part
						z.dat[1] = ((double *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(long long)), OPH_DOUBLE, OPH_LONG, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(long long)), OPH_DOUBLE, OPH_LONG, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_FLOAT:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = ((double *) (args->args[2]))[i];	//real part
						z.dat[1] = ((double *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(float)), OPH_DOUBLE, OPH_FLOAT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(float)), OPH_DOUBLE, OPH_FLOAT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_DOUBLE:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = ((double *) (args->args[2]))[i];	//real part
						z.dat[1] = ((double *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(double)), OPH_DOUBLE, OPH_DOUBLE, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(double)), OPH_DOUBLE, OPH_DOUBLE, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				default:
					pmesg(1, __FILE__, __LINE__, "Type not recognized\n");
					*length = 0;
					*is_null = 0;
					*error = 1;
					return NULL;
			}
			break;
		default:
			pmesg(1, __FILE__, __LINE__, "Type not recognized\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
	}

	*length = *(output->length);
	*error = 0;
	*is_null = 0;

	return output->content;
}
char* oph_gsl_ifft(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error)
{
	if (*error)
	{
	        *length=0;
	        *is_null=0;
	        *error=1;
	        return NULL;
	}
	if (*is_null || !args->lengths[2])
	{
	        *length=0;
	        *is_null=1;
	        *error=0;
	        return NULL;
	}

    if (!initid->ptr) {

        initid->ptr=(char *)calloc(1,sizeof(oph_string));
        if(!initid->ptr){
            pmesg(1,  __FILE__, __LINE__, "Error allocating result\n");
            *length=0;
            *is_null=1;
            *error=1;
            return NULL;
        }

        oph_stringPtr output = (oph_stringPtr) initid->ptr;

        core_set_type(output,args->args[1],&(args->lengths[1]));
        if (output->type!=OPH_COMPLEX_DOUBLE) {
        	pmesg(1,  __FILE__, __LINE__, "Invalid type: oph_complex_double required\n");
        	*length=0;
        	*is_null=1;
        	*error=1;
        	return NULL;
        }

        core_set_type(output,args->args[0],&(args->lengths[0]));
        if (output->type!=OPH_COMPLEX_DOUBLE) {
        	pmesg(1,  __FILE__, __LINE__, "Invalid type: oph_complex_double or oph_double required\n");
        	*length=0;
        	*is_null=1;
        	*error=1;
        	return NULL;
        }

        output->length = (unsigned long *)calloc(1,sizeof(unsigned long));
        if (!output->length) {
            pmesg(1,  __FILE__, __LINE__, "Error allocating length\n");
            *length=0;
            *is_null=1;
            *error=1;
            return NULL;
        }

        *(output->length) = args->lengths[2];

        if(core_set_elemsize(output)){
            pmesg(1,  __FILE__, __LINE__, "Error on setting element size\n");
            *length=0;
            *is_null=0;
            *error=1;
            return NULL;
        }

        if(core_set_numelem(output)){
            pmesg(1,  __FILE__, __LINE__, "Error on counting result elements\n");
            *length=0;
            *is_null=0;
            *error=1;
            return NULL;
        }

        output->content = (char *)calloc(1,*(output->length));
        if(!output->content){
            pmesg(1,  __FILE__, __LINE__, "Error allocating result string\n");
            *length=0;
            *is_null=1;
            *error=1;
            return NULL;
        }

        initid->extension = calloc(1,sizeof(oph_gsl_fft_extraspace));
        if (!initid->extension) {
            pmesg(1,  __FILE__, __LINE__, "Error allocating extra space\n");
            *length=0;
            *is_null=1;
            *error=1;
            return NULL;
        }

        oph_gsl_fft_extraspace *extra = (oph_gsl_fft_extraspace *) initid->extension;

        extra->wt = gsl_fft_complex_wavetable_alloc(output->numelem);
        if (!extra->wt) {
            pmesg(1,  __FILE__, __LINE__, "Error allocating wavetable\n");
            *length=0;
            *is_null=1;
            *error=1;
            return NULL;
        }

        extra->ws = gsl_fft_complex_workspace_alloc(output->numelem);
        if (!extra->ws) {
            pmesg(1,  __FILE__, __LINE__, "Error allocating workspace\n");
            *length=0;
            *is_null=1;
            *error=1;
            return NULL;
        }

    }

    oph_stringPtr output = (oph_stringPtr) initid->ptr;
    oph_gsl_fft_extraspace *extra = (oph_gsl_fft_extraspace *) initid->extension;

    gsl_set_error_handler_off();

    memcpy(output->content,args->args[2],*(output->length));
    if (gsl_fft_complex_inverse((gsl_complex_packed_array) output->content,1,output->numelem,extra->wt,extra->ws)) {
        pmesg(1,  __FILE__, __LINE__, "Error computing ifft\n");
        *length=0;
        *is_null=1;
        *error=1;
        return NULL;
    }

    *length = *(output->length);
    *error=0;
    *is_null=0;

    return output->content;
}
int env_set(HASHTBL * task_tbl, oph_operator_struct * handle)
{
	if (!handle) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Null Handle\n");
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_NULL_OPERATOR_HANDLE);
		return OPH_ANALYTICS_OPERATOR_NULL_OPERATOR_HANDLE;
	}

	if (!task_tbl) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Null operator string\n");
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_NULL_TASK_TABLE);
		return OPH_ANALYTICS_OPERATOR_BAD_PARAMETER;
	}

	if (handle->operator_handle) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Operator handle already initialized\n");
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_HANDLE_ALREADY_INITIALIZED);
		return OPH_ANALYTICS_OPERATOR_NOT_NULL_OPERATOR_HANDLE;
	}

	if (!(handle->operator_handle = (OPH_PRIMITIVES_LIST_operator_handle *) calloc(1, sizeof(OPH_PRIMITIVES_LIST_operator_handle)))) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_MEMORY_ERROR_HANDLE);
		return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
	}
	//1 - Set up struct to empty values
	((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->level = 0;
	((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->func_ret = NULL;
	((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->func_type = NULL;
	((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->name_filter = NULL;
	((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->limit = 0;
	((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->id_dbms = 0;
	((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->server = NULL;
	ophidiadb *oDB = &((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->oDB;
	((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->objkeys = NULL;
	((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->objkeys_num = -1;

	//Only master process has to continue
	if (handle->proc_rank != 0)
		return OPH_ANALYTICS_OPERATOR_SUCCESS;

	oph_odb_init_ophidiadb(oDB);

	//3 - Fill struct with the correct data
	char *value;

	// retrieve objkeys
	value = hashtbl_get(task_tbl, OPH_IN_PARAM_OBJKEY_FILTER);
	if (!value) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Missing input parameter %s\n", OPH_IN_PARAM_OBJKEY_FILTER);
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_FRAMEWORK_MISSING_INPUT_PARAMETER, OPH_IN_PARAM_OBJKEY_FILTER);
		return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
	}
	if (oph_tp_parse_multiple_value_param
	    (value, &((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->objkeys, &((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->objkeys_num)) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Operator string not valid\n");
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "Operator string not valid\n");
		oph_tp_free_multiple_value_param_list(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->objkeys,
						      ((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->objkeys_num);
		return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
	}

	value = hashtbl_get(task_tbl, OPH_IN_PARAM_PRIMITIVE_NAME_FILTER);
	if (!value) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Missing input parameter %s\n", OPH_IN_PARAM_PRIMITIVE_NAME_FILTER);
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_MISSING_INPUT_PARAMETER, "NO-CONTAINER", OPH_IN_PARAM_PRIMITIVE_NAME_FILTER);
		return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
	}
	if (!(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->name_filter = (char *) strndup(value, OPH_TP_TASKLEN))) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_MEMORY_ERROR_INPUT, "name_filter");
		return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
	}

	value = hashtbl_get(task_tbl, OPH_IN_PARAM_LIMIT_FILTER);
	if (!value) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Missing input parameter %s\n", OPH_IN_PARAM_LIMIT_FILTER);
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_MISSING_INPUT_PARAMETER, "NO-CONTAINER", OPH_IN_PARAM_LIMIT_FILTER);
		return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
	}
	((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->limit = (int) strtol(value, NULL, 10);
	if (((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->limit < 0) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Limit must be positive\n");
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_BAD_LIMIT, OPH_IN_PARAM_LIMIT_FILTER);
		return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
	}

	value = hashtbl_get(task_tbl, OPH_IN_PARAM_VISUALIZZATION_LEVEL);
	if (!value) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Missing input parameter %s\n", OPH_IN_PARAM_VISUALIZZATION_LEVEL);
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_MISSING_INPUT_PARAMETER, "NO-CONTAINER", OPH_IN_PARAM_VISUALIZZATION_LEVEL);
		return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
	}
	((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->level = (int) strtol(value, NULL, 10);
	if (((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->level < 1 || ((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->level > 5) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Level unrecognized\n");
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_BAD_LEVEL);
		return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
	}

	value = hashtbl_get(task_tbl, OPH_IN_PARAM_DBMS_ID_FILTER);
	if (!value) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Missing input parameter %s\n", OPH_IN_PARAM_DBMS_ID_FILTER);
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_MISSING_INPUT_PARAMETER, "NO-CONTAINER", OPH_IN_PARAM_DBMS_ID_FILTER);
		return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
	}
	if (strcmp(value, OPH_COMMON_DEFAULT_EMPTY_VALUE) == 0) {
		((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->id_dbms = 0;
	} else {
		((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->id_dbms = (int) strtol(value, NULL, 10);
		if (((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->id_dbms < 1) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "id of dbms must be positive\n");
			logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_BAD_LIMIT, OPH_IN_PARAM_DBMS_ID_FILTER);
			return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
		}
	}

	value = hashtbl_get(task_tbl, OPH_IN_PARAM_PRIMITIVE_RETURN_TYPE_FILTER);
	if (!value) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Missing input parameter %s\n", OPH_IN_PARAM_PRIMITIVE_RETURN_TYPE_FILTER);
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_MISSING_INPUT_PARAMETER, "NO-CONTAINER", OPH_IN_PARAM_PRIMITIVE_RETURN_TYPE_FILTER);
		return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
	}
	if (strcmp(value, OPH_COMMON_ALL_FILTER) != 0) {
		if (!(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->func_ret = (char *) strndup(value, OPH_TP_TASKLEN))) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
			logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_MEMORY_ERROR_INPUT, "func_ret");
			return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
		}
	}

	value = hashtbl_get(task_tbl, OPH_IN_PARAM_PRIMITIVE_TYPE_FILTER);
	if (!value) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Missing input parameter %s\n", OPH_IN_PARAM_PRIMITIVE_TYPE_FILTER);
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_MISSING_INPUT_PARAMETER, "NO-CONTAINER", OPH_IN_PARAM_PRIMITIVE_TYPE_FILTER);
		return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
	}
	if (strcmp(value, OPH_COMMON_ALL_FILTER) != 0) {
		if (!(((OPH_PRIMITIVES_LIST_operator_handle *) handle->operator_handle)->func_type = (char *) strndup(value, OPH_TP_TASKLEN))) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
			logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_PRIMITIVES_LIST_MEMORY_ERROR_INPUT, "func_type");
			return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
		}
	}

	return OPH_ANALYTICS_OPERATOR_SUCCESS;
}
char* oph_extend(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error)
{
	oph_multistring *multim;
        oph_multistring *output;

	int number = 1;

        if(!initid->extension){
                if(core_set_oph_multistring( (oph_multistring**)(&(initid->extension)), args->args[0], &(args->lengths[0]))){
                        pmesg(1, __FILE__, __LINE__, "Error setting measure structure\n");
                        *length=0;
                        *is_null=0;
                        *error=1;
                        return NULL;
                }
        }

        if(!initid->ptr){
                if(core_set_oph_multistring( ((oph_multistring**)(&(initid->ptr))), args->args[1], &(args->lengths[1]))){
                        pmesg(1, __FILE__, __LINE__, "Error setting measure structure\n");
                        *length=0;
                        *is_null=0;
                        *error=1;
                        return NULL;
                }
                //Check
                if( ((oph_multistring*)(initid->ptr))->num_measure != ((oph_multistring*)(initid->extension))->num_measure){
                	pmesg(1, __FILE__, __LINE__, "Wrong input or output type\n");
                	*length=0;
                     	*is_null=0;
                	*error=1;
                	return NULL;
                }
	}
        multim = (oph_multistring*)(initid->extension);
        multim->content = args->args[2];
        multim->length = args->lengths[2];

        //Check
        if(multim->length%multim->blocksize){
        	pmesg(1,  __FILE__, __LINE__, "Wrong input type or data corrupted\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
	}
        multim->numelem = multim->length/multim->blocksize;
        output = (oph_multistring*)(initid->ptr);

	if (args->arg_count>3)
	{
		number = *((long long*)args->args[3]);
		if (number < 1)
		{
			pmesg(1,  __FILE__, __LINE__, "Wrong number of replies.\n");
		        *length=0;
		        *is_null=0;
		        *error=1;
		        return NULL;
		}
	}

	output->numelem = multim->numelem * number;

	/* Allocate the right space for the result set */
        if(!output->content){
                output->content=(char *)calloc(1,(output->numelem)*(output->blocksize));
                if(!output->content){
                        pmesg(1,  __FILE__, __LINE__, "Error allocating measures string\n");
                        *length=0;
                        *is_null=0;
                        *error=1;
                        return NULL;
                }
        }

        if(core_oph_extend_multi(multim, output, number)){
        	pmesg(1,  __FILE__, __LINE__, "Unable to compute result\n");
                *length=0;
                *is_null=1;
                *error=1;
                return NULL;
        }
	*length=(output->numelem)*(output->blocksize);
        *error=0;
        *is_null=0;
        return (result = ((oph_multistring*)initid->ptr)->content);

}
char *oph_concat2(UDF_INIT * initid, UDF_ARGS * args, char *result, unsigned long *length, char *is_null, char *error)
{
	int i;

	if (*error) {
		*length = 0;
		*is_null = 0;
		*error = 1;
		return NULL;
	}
	if (*is_null) {
		*length = 0;
		*is_null = 1;
		*error = 0;
		return NULL;
	}
	for (i = 2; i < args->arg_count; ++i) {
		if (!args->lengths[i]) {
			*length = 0;
			*is_null = 1;
			*error = 0;
			return NULL;
		}
	}

	oph_generic_param_multi *param;
	if (!initid->ptr) {
		param = (oph_generic_param_multi *) malloc(sizeof(oph_generic_param_multi));
		if (!param) {
			pmesg(1, __FILE__, __LINE__, "Error in allocating parameters\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		param->measure = NULL;
		param->result = NULL;
		param->error = 0;
		param->core_oph_oper = NULL;

		initid->ptr = (char *) param;
	} else
		param = (oph_generic_param_multi *) initid->ptr;

	if (param->error) {
		*length = 0;
		*is_null = 0;
		*error = 1;
		return NULL;
	}

	unsigned long numelem_total = 0;
	oph_multistring *measure;
	if (!param->error && !param->measure) {
		if (core_set_oph_multistring(&measure, args->args[0], &args->lengths[0])) {
			param->error = 1;
			pmesg(1, __FILE__, __LINE__, "Error setting measure structure\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		int j;
		for (i = 0; i < args->arg_count - 2; ++i) {
			measure[i].length = args->lengths[2 + i];
			if ((measure[i].length % measure[i].blocksize) || (measure[i].islast != (i < args->arg_count - 3 ? 0 : 1))) {
				param->error = 1;
				pmesg(1, __FILE__, __LINE__, "Wrong input type or data corrupted\n");
				*length = 0;
				*is_null = 0;
				*error = 1;
				return NULL;
			}
			measure[i].numelem = measure[i].length / measure[i].blocksize;
			if (i <= 1)
				numelem_total += measure[i].numelem;	// Almost two measures are considered
			if (measure->num_measure != measure[i].num_measure) {
				param->error = 1;
				pmesg(1, __FILE__, __LINE__, "Wrong input data types\n");
				*length = 0;
				*is_null = 0;
				*error = 1;
				return NULL;
			} else
				for (j = 0; j < measure->num_measure; ++j) {
					if (measure[i].type[j] != measure->type[j]) {
						param->error = 1;
						pmesg(1, __FILE__, __LINE__, "Data types of input arrays are different\n");
						*length = 0;
						*is_null = 0;
						*error = 1;
						return NULL;
					}
				}
		}
		measure->param = args->arg_count > 3 ? 1 : 0;

		param->measure = measure;
	} else {
		measure = param->measure;
		if (args->arg_count > 3) {
			measure->param++;
			if (measure->param > args->arg_count - 3)
				measure->param = 1;
		}
	}

	for (i = 0; i < args->arg_count - 2; ++i)
		measure[i].content = args->args[2 + i];

	oph_multistring *output;
	if (!param->error && !param->result) {
		if (core_set_oph_multistring(&output, args->args[1], &(args->lengths[1]))) {
			param->error = 1;
			pmesg(1, __FILE__, __LINE__, "Error setting measure structure\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		output->numelem = numelem_total;
		output->length = output->numelem * output->blocksize;
		if (!output->length) {
			*length = 0;
			*is_null = 1;
			*error = 0;
			return NULL;
		}
		output->content = (char *) malloc(output->length);
		if (!output->content) {
			param->error = 1;
			pmesg(1, __FILE__, __LINE__, "Error allocating measures string\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		param->result = output;
	} else
		output = param->result;

	if (!param->error && core_oph_concat2_multi(param)) {
		param->error = 1;
		pmesg(1, __FILE__, __LINE__, "Unable to compute result\n");
		*length = 0;
		*is_null = 0;
		*error = 1;
		return NULL;
	}

	*length = output->length;
	*error = 0;
	*is_null = 0;

	return (result = output->content);
}
int env_set (HASHTBL *task_tbl, oph_operator_struct *handle)
{
  if (!handle){
  	pmesg(LOG_ERROR, __FILE__, __LINE__, "Null Handle\n");
	  return OPH_ANALYTICS_OPERATOR_NULL_OPERATOR_HANDLE;
  }

  if (!task_tbl){
	  pmesg(LOG_ERROR, __FILE__, __LINE__, "Null operator string\n");
      return OPH_ANALYTICS_OPERATOR_BAD_PARAMETER;
  }

  if (handle->operator_handle){
	pmesg(LOG_ERROR, __FILE__, __LINE__, "Operator handle already initialized\n");
    return OPH_ANALYTICS_OPERATOR_NOT_NULL_OPERATOR_HANDLE;
  }

  if (!(handle->operator_handle = (OPH_DELETECONTAINER_operator_handle *) calloc (1, sizeof (OPH_DELETECONTAINER_operator_handle)))){
	pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
    logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_DELETECONTAINER_MEMORY_ERROR_HANDLE );
    return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
  }

  //1 - Set up struct to empty values
  ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->id_input_container = 0;
  ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->container_input = NULL;
  ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->cwd = NULL;
  ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->user = NULL;
  ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->hidden = 0;
  ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->delete_type = 0;
  ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->objkeys = NULL;
  ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->objkeys_num = -1;
  ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->sessionid = NULL;

  ophidiadb *oDB = &((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->oDB;
  oph_odb_init_ophidiadb(oDB);	

  //Only master process has to continue
  if (handle->proc_rank != 0)
	return OPH_ANALYTICS_OPERATOR_SUCCESS;

  //3 - Fill struct with the correct data
  char *container_name, *value;

  // retrieve objkeys
  value = hashtbl_get(task_tbl, OPH_IN_PARAM_OBJKEY_FILTER);
  if(!value){
    pmesg(LOG_ERROR, __FILE__, __LINE__, "Missing input parameter %s\n", OPH_IN_PARAM_OBJKEY_FILTER);
    logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_FRAMEWORK_MISSING_INPUT_PARAMETER, OPH_IN_PARAM_OBJKEY_FILTER );
    return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
  }
  if(oph_tp_parse_multiple_value_param(value, &((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->objkeys, &((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->objkeys_num)){
    pmesg(LOG_ERROR, __FILE__, __LINE__, "Operator string not valid\n");
    logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "Operator string not valid\n");
    oph_tp_free_multiple_value_param_list(((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->objkeys, ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->objkeys_num);
    return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
  }

  // retrieve sessionid
  value = hashtbl_get(task_tbl, OPH_ARG_SESSIONID);
  if(!value){
	pmesg(LOG_ERROR, __FILE__, __LINE__, "Missing input parameter %s\n", OPH_ARG_SESSIONID);
    logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_FRAMEWORK_MISSING_INPUT_PARAMETER, OPH_ARG_SESSIONID);
	return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
  }
  if(!(((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->sessionid = (char *) strndup (value, OPH_TP_TASKLEN))){
	pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
    logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_GENERIC_MEMORY_ERROR_INPUT, "sessionid" );
	return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
  }

  container_name = (!hashtbl_get(task_tbl, OPH_IN_PARAM_CONTAINER_INPUT) ? "NO-CONTAINER" : hashtbl_get(task_tbl, OPH_IN_PARAM_CONTAINER_INPUT));
  value = hashtbl_get(task_tbl, OPH_IN_PARAM_CONTAINER_INPUT);
  if(!value){
	pmesg(LOG_ERROR, __FILE__, __LINE__, "Missing input parameter %s\n", OPH_IN_PARAM_CONTAINER_INPUT);
    logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_DELETECONTAINER_MISSING_INPUT_PARAMETER, container_name, OPH_IN_PARAM_CONTAINER_INPUT );
    return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
  }
  if(!(((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->container_input = (char *) strndup (value, OPH_TP_TASKLEN))){
	pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
	logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_DELETECONTAINER_MEMORY_ERROR_INPUT_NO_CONTAINER, container_name, "container output name" );
	return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
  }	

  value = hashtbl_get(task_tbl, OPH_IN_PARAM_CWD);
  if(!value){
	pmesg(LOG_ERROR, __FILE__, __LINE__, "Missing input parameter %s\n", OPH_IN_PARAM_CWD);
	logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_DELETECONTAINER_MISSING_INPUT_PARAMETER, container_name, OPH_IN_PARAM_CWD );
	return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
  }
  if(!(((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->cwd = (char *) strndup (value, OPH_TP_TASKLEN))){
	pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
	logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_DELETECONTAINER_MEMORY_ERROR_INPUT_NO_CONTAINER, container_name, "input path" );
	
	return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
  }	

  value = hashtbl_get(task_tbl, OPH_ARG_USERNAME);
  if(!value){
	pmesg(LOG_ERROR, __FILE__, __LINE__, "Missing input parameter %s\n", OPH_ARG_USERNAME);
	logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_DELETECONTAINER_MISSING_INPUT_PARAMETER, container_name, OPH_ARG_USERNAME );
	return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
  }
  if(!(((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->user = (char *) strndup (value, OPH_TP_TASKLEN))){
	pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
	logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_DELETECONTAINER_MEMORY_ERROR_INPUT_NO_CONTAINER, container_name, "username" );
  }

  value = hashtbl_get(task_tbl, OPH_IN_PARAM_DELETE_TYPE);
  if(!value){
	pmesg(LOG_ERROR, __FILE__, __LINE__, "Missing input parameter %s\n", OPH_IN_PARAM_DELETE_TYPE);
	logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_DELETECONTAINER_MISSING_INPUT_PARAMETER, container_name, OPH_IN_PARAM_DELETE_TYPE );
	return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
  }
  if( !strcmp(value, OPH_DELETE_PHYSIC_TYPE) ){
	((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->delete_type = OPH_DELETE_PHYSIC_CODE;
  }
  else{
	((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->delete_type = OPH_DELETE_LOGIC_CODE;
  }

  value = hashtbl_get(task_tbl, OPH_IN_PARAM_HIDDEN);
  if(!value){
	pmesg(LOG_ERROR, __FILE__, __LINE__, "Missing input parameter %s\n", OPH_IN_PARAM_HIDDEN);
	logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_DELETECONTAINER_MISSING_INPUT_PARAMETER, container_name, OPH_IN_PARAM_HIDDEN );
	return OPH_ANALYTICS_OPERATOR_INVALID_PARAM;
  }
  if( !strcmp(value, OPH_COMMON_NO_VALUE) ){
	  ((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->hidden = 0;
  }
  else{
	((OPH_DELETECONTAINER_operator_handle*)handle->operator_handle)->hidden = 1;
  }

  if(oph_odb_read_ophidiadb_config_file(oDB)){
	pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to read OphidiaDB configuration\n");
    logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_DELETECONTAINER_OPHIDIADB_CONFIGURATION_FILE, container_name );
	return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
  }

  if( oph_odb_connect_to_ophidiadb(oDB)){
	pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to connect to OphidiaDB. Check access parameters.\n");
	logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_DELETECONTAINER_OPHIDIADB_CONNECTION_ERROR, container_name );
	return OPH_ANALYTICS_OPERATOR_MYSQL_ERROR;
  }

  return OPH_ANALYTICS_OPERATOR_SUCCESS;
}
char* oph_ccluster_kcluster(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error)
{
    if(!initid->ptr){
        *error=0;
        *is_null=0;

        initid->ptr=(char *)calloc(1,sizeof(oph_string));
        if(!initid->ptr){
            pmesg(1,  __FILE__, __LINE__, "Error allocating result\n");
            *length=0;
            *is_null=1;
            *error=1;
            return NULL;
        }
        initid->extension = calloc(1,sizeof(oph_ccluster_kcluster_extra));
        if(!initid->extension){
            pmesg(1,  __FILE__, __LINE__, "Error allocating extension\n");
            *length=0;
            *is_null=1;
            *error=1;
            return NULL;
        }

        oph_ccluster_kcluster_extra *extra = (oph_ccluster_kcluster_extra *) initid->extension;

        extra->k = (int) *((long long*) args->args[3]); // set cluster number
        extra->method = OPH_CCLUSTER_KCLUSTER_KMEANS; // default method
        extra->level = OPH_CCLUSTER_KCLUSTER_ALL; // default level
        extra->npass = 1; // default npass
        extra->type = OPH_DOUBLE; // default input type

	if (!strncasecmp(args->args[0],"OPH_INT",args->lengths[0])) extra->type = OPH_INT;
	else if (!strncasecmp(args->args[0],"OPH_SHORT",args->lengths[0])) extra->type = OPH_SHORT;
	else if (!strncasecmp(args->args[0],"OPH_BYTE",args->lengths[0])) extra->type = OPH_BYTE;
	else if (!strncasecmp(args->args[0],"OPH_LONG",args->lengths[0])) extra->type = OPH_LONG;
	else if (!strncasecmp(args->args[0],"OPH_FLOAT",args->lengths[0])) extra->type = OPH_FLOAT;
	else if (!strncasecmp(args->args[0],"OPH_DOUBLE",args->lengths[0])) extra->type = OPH_DOUBLE;
	else {
		pmesg(1,  __FILE__, __LINE__, "Invalid input data type!\n");
		*length=0;
		*is_null=0;
		*error=1;
		return NULL;
	}

        int i;
        for (i = 4; i < args->arg_count; i++) {
                if (args->arg_type[i]==INT_RESULT) { // npass
                    extra->npass = (int) *((long long*) args->args[i]);
                    if (extra->npass < 1) {
                        pmesg(1,  __FILE__, __LINE__, "npass must be >= 1!\n");
                        *length=0;
                        *is_null=0;
                        *error=1;
                        return NULL;
                    }
                } else if (args->arg_type[i]==STRING_RESULT) {
                    if (!strncasecmp(args->args[i],"KMEANS",args->lengths[i])) {
                        extra->method = OPH_CCLUSTER_KCLUSTER_KMEANS;
                    } else if (!strncasecmp(args->args[i],"KMEDIANS",args->lengths[i])) {
                        extra->method = OPH_CCLUSTER_KCLUSTER_KMEDIANS;
                    } else if (!strncasecmp(args->args[i],"CENTROIDS",args->lengths[i])) {
                        extra->level = OPH_CCLUSTER_KCLUSTER_CENTROIDS;
                    } else if (!strncasecmp(args->args[i],"LABELS",args->lengths[i])) {
                        extra->level = OPH_CCLUSTER_KCLUSTER_LABELS;
                    } else if (!strncasecmp(args->args[i],"ALL",args->lengths[i])) {
                        extra->level = OPH_CCLUSTER_KCLUSTER_ALL;
                    } else {
                        pmesg(1,  __FILE__, __LINE__, "invalid argument %d!\n",i);
                        *length=0;
                        *is_null=0;
                        *error=1;
                        return NULL;
                    }
                } else {
                    pmesg(1,  __FILE__, __LINE__, "wrong type for argument %d!\n",i);
                    *length=0;
                    *is_null=0;
                    *error=1;
                    return NULL;
                }
        }

        extra->npoints = args->lengths[2] / core_sizeof(extra->type);

        extra->data = (double **) malloc(sizeof(double *) * extra->npoints);
        if (!extra->data) {
            pmesg(1,  __FILE__, __LINE__, "Error allocating memory\n");
            *length=0;
            *is_null=0;
            *error=1;
            return NULL;
        }
        for (i = 0; i < extra->npoints; i++) {
            extra->data[i] = (double *) malloc(sizeof(double));
            if (!extra->data[i]) {
                pmesg(1,  __FILE__, __LINE__, "Error allocating memory\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
            }
        }

        extra->mask = (int **) malloc(sizeof(int *) * extra->npoints);
        if (!extra->mask) {
            pmesg(1,  __FILE__, __LINE__, "Error allocating memory\n");
            *length=0;
            *is_null=0;
            *error=1;
            return NULL;
        }
        for (i = 0; i < extra->npoints; i++) {
            extra->mask[i] = (int *) malloc(sizeof(int));
            if (!extra->mask[i]) {
                pmesg(1,  __FILE__, __LINE__, "Error allocating memory\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
            }
        }

        extra->clusterid = (int *) malloc(sizeof(int) * extra->npoints);
        if (!extra->clusterid) {
            pmesg(1,  __FILE__, __LINE__, "Error allocating memory\n");
            *length=0;
            *is_null=0;
            *error=1;
            return NULL;
        }

        oph_stringPtr output = (oph_stringPtr) initid->ptr;

        if (extra->level==OPH_CCLUSTER_KCLUSTER_CENTROIDS) {
            extra->cdata = (double **) malloc(sizeof(double *) * extra->k);
            if (!extra->cdata) {
                pmesg(1,  __FILE__, __LINE__, "Error allocating memory\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
            }
            for (i = 0; i < extra->k; i++) {
                extra->cdata[i] = (double *) malloc(sizeof(double));
                if (!extra->cdata[i]) {
                    pmesg(1,  __FILE__, __LINE__, "Error allocating memory\n");
                    *length=0;
                    *is_null=0;
                    *error=1;
                    return NULL;
                }
            }

            extra->cmask = (int **) malloc(sizeof(int *) * extra->k);
            if (!extra->cmask) {
                pmesg(1,  __FILE__, __LINE__, "Error allocating memory\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
            }
            for (i = 0; i < extra->k; i++) {
                extra->cmask[i] = (int *) malloc(sizeof(int));
                if (!extra->cmask[i]) {
                    pmesg(1,  __FILE__, __LINE__, "Error allocating memory\n");
                    *length=0;
                    *is_null=0;
                    *error=1;
                    return NULL;
                }
            }

            unsigned long len = (unsigned long ) strlen("OPH_DOUBLE");
            core_set_type(output, "OPH_DOUBLE" ,&len);
            if(core_set_elemsize(output)){
                pmesg(1,  __FILE__, __LINE__, "Error on setting result elements size\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
            }

            output->length = (unsigned long *) malloc(sizeof(unsigned long));
            if (!output->length) {
                pmesg(1,  __FILE__, __LINE__, "Error allocating length\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
            }
            *(output->length) = (unsigned long) extra->k * output->elemsize;

            output->content = (char *) malloc(*(output->length));
            if (!output->content) {
                pmesg(1,  __FILE__, __LINE__, "Error allocating output\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
            }

            if(core_set_numelem(output)){
                pmesg(1,  __FILE__, __LINE__, "Error on counting result elements\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
            }
        } else if (extra->level==OPH_CCLUSTER_KCLUSTER_ALL) {
            extra->cdata = (double **) malloc(sizeof(double *) * extra->k);
            if (!extra->cdata) {
                pmesg(1,  __FILE__, __LINE__, "Error allocating memory\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
            }
            for (i = 0; i < extra->k; i++) {
                extra->cdata[i] = (double *) malloc(sizeof(double));
                if (!extra->cdata[i]) {
                    pmesg(1,  __FILE__, __LINE__, "Error allocating memory\n");
                    *length=0;
                    *is_null=0;
                    *error=1;
                    return NULL;
                }
            }

            extra->cmask = (int **) malloc(sizeof(int *) * extra->k);
            if (!extra->cmask) {
                pmesg(1,  __FILE__, __LINE__, "Error allocating memory\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
            }
            for (i = 0; i < extra->k; i++) {
                extra->cmask[i] = (int *) malloc(sizeof(int));
                if (!extra->cmask[i]) {
                    pmesg(1,  __FILE__, __LINE__, "Error allocating memory\n");
                    *length=0;
                    *is_null=0;
                    *error=1;
                    return NULL;
                }
            }

            unsigned long len = (unsigned long ) strlen("OPH_DOUBLE");
            core_set_type(output, "OPH_DOUBLE" ,&len);
            if(core_set_elemsize(output)){
                pmesg(1,  __FILE__, __LINE__, "Error on setting result elements size\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
            }

            output->length = (unsigned long *) malloc(sizeof(unsigned long));
            if (!output->length) {
                pmesg(1,  __FILE__, __LINE__, "Error allocating length\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
            }
            *(output->length) = (unsigned long) extra->npoints * output->elemsize;

            output->content = (char *) malloc(*(output->length));
            if (!output->content) {
                pmesg(1,  __FILE__, __LINE__, "Error allocating output\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
            }

            if(core_set_numelem(output)){
                pmesg(1,  __FILE__, __LINE__, "Error on counting result elements\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
            }
        } else {
            unsigned long len = (unsigned long ) strlen("OPH_INT");
            core_set_type(output, "OPH_INT" ,&len);
            if(core_set_elemsize(output)){
                pmesg(1,  __FILE__, __LINE__, "Error on setting result elements size\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
            }

            output->length = (unsigned long *) malloc(sizeof(unsigned long));
            if (!output->length) {
                pmesg(1,  __FILE__, __LINE__, "Error allocating length\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
            }
            *(output->length) = (unsigned long) extra->npoints * output->elemsize;

            output->content = (char *) malloc(*(output->length));
            if (!output->content) {
                pmesg(1,  __FILE__, __LINE__, "Error allocating output\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
            }

            if(core_set_numelem(output)){
                pmesg(1,  __FILE__, __LINE__, "Error on counting result elements\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
            }
        }
    }

    if (*error)
    {
        *length=0;
        *is_null=0;
        *error=1;
        return NULL;
    }
    if (*is_null)
    {
        *length=0;
        *is_null=1;
        *error=0;
        return NULL;
    }

    oph_stringPtr output = (oph_stringPtr) initid->ptr;
    oph_ccluster_kcluster_extra *extra = (oph_ccluster_kcluster_extra *) initid->extension;

    double weight[1] = {1.0};
    char method = (extra->method==OPH_CCLUSTER_KCLUSTER_KMEANS)?'a':'m';
    double err;
    int ifound;
    int n;

    switch (extra->type) {
        case OPH_INT:
            for (n = 0; n < extra->npoints; n++) {
                extra->data[n][0] = (double) ((int *)(args->args[2]))[n];
                extra->mask[n][0] = 1;
            }
            break;
        case OPH_SHORT:
            for (n = 0; n < extra->npoints; n++) {
                extra->data[n][0] = (double) ((short *)(args->args[2]))[n];
                extra->mask[n][0] = 1;
            }
            break;
        case OPH_BYTE:
            for (n = 0; n < extra->npoints; n++) {
                extra->data[n][0] = (double) ((char *)(args->args[2]))[n];
                extra->mask[n][0] = 1;
            }
            break;
        case OPH_LONG:
            for (n = 0; n < extra->npoints; n++) {
                extra->data[n][0] = (double) ((long long *)(args->args[2]))[n];
                extra->mask[n][0] = 1;
            }
            break;
        case OPH_FLOAT:
            for (n = 0; n < extra->npoints; n++) {
                extra->data[n][0] = (double) ((float *)(args->args[2]))[n];
                if (isnan(extra->data[n][0])) {
                    extra->mask[n][0] = 0;
                } else {
                    extra->mask[n][0] = 1;
                }
            }
            break;
        case OPH_DOUBLE:
            for (n = 0; n < extra->npoints; n++) {
                extra->data[n][0] = ((double *)(args->args[2]))[n];
                if (isnan(extra->data[n][0])) {
                    extra->mask[n][0] = 0;
                } else {
                    extra->mask[n][0] = 1;
                }
            }
            break;
        default:
            pmesg(1,  __FILE__, __LINE__, "Invalid input type\n");
            *length=0;
            *is_null=0;
            *error=1;
            return NULL;
    }

    kcluster(extra->k,extra->npoints,1,extra->data,extra->mask,weight,0,extra->npass,method,'e',extra->clusterid,&err,&ifound);

    if(ifound==0){
        pmesg(1,  __FILE__, __LINE__, "k > number of points!\n");
        *length=0;
        *is_null=0;
        *error=1;
        return NULL;
    }
    if(ifound==-1){
        pmesg(1,  __FILE__, __LINE__, "Error allocating memory for clustering\n");
        *length=0;
        *is_null=0;
        *error=1;
        return NULL;
    }

    if (extra->level==OPH_CCLUSTER_KCLUSTER_CENTROIDS) {
        if (!getclustercentroids(extra->k,extra->npoints,1,extra->data,extra->mask,extra->clusterid,extra->cdata,extra->cmask,0,method)) {
            pmesg(1,  __FILE__, __LINE__, "Error allocating memory for centroids retrieval\n");
            *length=0;
            *is_null=0;
            *error=1;
            return NULL;
        }
        for (n = 0; n < extra->k; n++) {
            if (extra->cmask[n][0]==0) {
                pmesg(1,  __FILE__, __LINE__, "All cluster members are missing for cluster %d\n",n);
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
            } else {
                ((double *)(output->content))[n] = extra->cdata[n][0];
            }
        }
    } else if (extra->level==OPH_CCLUSTER_KCLUSTER_ALL) {
        if (!getclustercentroids(extra->k,extra->npoints,1,extra->data,extra->mask,extra->clusterid,extra->cdata,extra->cmask,0,method)) {
            pmesg(1,  __FILE__, __LINE__, "Error allocating memory for centroids retrieval\n");
            *length=0;
            *is_null=0;
            *error=1;
            return NULL;
        }
        for (n = 0; n < extra->npoints; n++) {
            if (extra->cmask[extra->clusterid[n]][0]==0) {
                pmesg(1,  __FILE__, __LINE__, "All cluster members are missing for cluster %d\n",extra->clusterid[n]);
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
            } else {
                ((double *)(output->content))[n] = extra->cdata[extra->clusterid[n]][0];
            }
        }
    } else {
        memcpy(output->content,extra->clusterid,*(output->length));
    }

    *length=*(output->length);
    return output->content;
}