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_SEARCH_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;

	int folderid;
	char *abs_path = NULL;
	char *filters = NULL;
	int *max_lengths = NULL;
	int max_lengths_size;
	int permission = 0;
	ophidiadb *oDB = &((OPH_SEARCH_operator_handle *) handle->operator_handle)->oDB;

	if (!strcasecmp(((OPH_SEARCH_operator_handle *) handle->operator_handle)->path, OPH_FRAMEWORK_FS_DEFAULT_PATH)) {
		if (oph_odb_fs_path_parsing(".", ((OPH_SEARCH_operator_handle *) handle->operator_handle)->cwd, &folderid, &abs_path, oDB)) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to parse path\n");
			logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_SEARCH_PATH_PARSING_ERROR);
			return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
		}
	} else {
		if (oph_odb_fs_path_parsing(((OPH_SEARCH_operator_handle *) handle->operator_handle)->path, ((OPH_SEARCH_operator_handle *) handle->operator_handle)->cwd, &folderid, &abs_path, oDB)) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to parse path '%s/%s'\n", ((OPH_SEARCH_operator_handle *) handle->operator_handle)->cwd,
			      ((OPH_SEARCH_operator_handle *) handle->operator_handle)->path);
			logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_SEARCH_PATH_PARSING_ERROR);
			return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
		}
	}
	if ((oph_odb_fs_check_folder_session(folderid, ((OPH_SEARCH_operator_handle *) handle->operator_handle)->sessionid, oDB, &permission)) || !permission) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Path %s not allowed\n", abs_path);
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_SEARCH_PATH_NOT_ALLOWED_ERROR, abs_path);
		if (abs_path) {
			free(abs_path);
			abs_path = NULL;
		}
		return OPH_ANALYTICS_OPERATOR_BAD_PARAMETER;
	}
	// Change folder_to_be_printed in user format
	if (abs_path) {
		char old_abs_path[1 + strlen(abs_path)];
		strcpy(old_abs_path, abs_path);
		free(abs_path);
		abs_path = NULL;
		if (oph_pid_drop_session_prefix(old_abs_path, ((OPH_SEARCH_operator_handle *) handle->operator_handle)->sessionid, &abs_path)) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Folder conversion error\n");
			logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "Folder conversion error\n");
			if (abs_path) {
				free(abs_path);
				abs_path = NULL;
			}
			return OPH_ANALYTICS_OPERATOR_BAD_PARAMETER;
		}
	}

	if (get_filters_string
	    (((OPH_SEARCH_operator_handle *) handle->operator_handle)->container_filter, ((OPH_SEARCH_operator_handle *) handle->operator_handle)->container_filter_num,
	     ((OPH_SEARCH_operator_handle *) handle->operator_handle)->metadata_key_filter, ((OPH_SEARCH_operator_handle *) handle->operator_handle)->metadata_key_filter_num,
	     ((OPH_SEARCH_operator_handle *) handle->operator_handle)->metadata_value_filter, ((OPH_SEARCH_operator_handle *) handle->operator_handle)->metadata_value_filter_num, &filters)) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to parse filters\n");
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_SEARCH_FILTERS_PARSING_ERROR);
		if (abs_path) {
			free(abs_path);
			abs_path = NULL;
		}
		return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
	}
	if (recursive_get_max_lengths(strlen(abs_path), folderid, filters, oDB, &max_lengths, &max_lengths_size, NULL, 1)) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Search error\n");
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_SEARCH_SEARCH_ERROR);
		if (abs_path) {
			free(abs_path);
			abs_path = NULL;
		}
		if (filters) {
			free(filters);
			filters = NULL;
		}
		return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
	}
	if (recursive_search
	    (abs_path, folderid, filters, oDB, max_lengths, max_lengths_size, NULL, NULL, 1, handle->operator_json,
	     oph_json_is_objkey_printable(((OPH_SEARCH_operator_handle *) handle->operator_handle)->objkeys, ((OPH_SEARCH_operator_handle *) handle->operator_handle)->objkeys_num,
					  OPH_JSON_OBJKEY_SEARCH))) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Search error\n");
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_SEARCH_SEARCH_ERROR);
		if (abs_path) {
			free(abs_path);
			abs_path = NULL;
		}
		if (filters) {
			free(filters);
			filters = NULL;
		}
		if (max_lengths) {
			free(max_lengths);
			max_lengths = NULL;
		}
		return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
	}

	if (abs_path) {
		free(abs_path);
		abs_path = NULL;
	}
	if (filters) {
		free(filters);
		filters = NULL;
	}
	if (max_lengths) {
		free(max_lengths);
		max_lengths = NULL;
	}

	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_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_SPLIT_operator_handle *) handle->operator_handle)->id_input_container, OPH_LOG_OPH_SPLIT_NULL_OPERATOR_HANDLE);
		return OPH_ANALYTICS_OPERATOR_NULL_OPERATOR_HANDLE;
	}

	if (((OPH_SPLIT_operator_handle *) handle->operator_handle)->fragment_id_start_position < 0 && handle->proc_rank != 0)
		return OPH_ANALYTICS_OPERATOR_SUCCESS;

	((OPH_SPLIT_operator_handle *) handle->operator_handle)->execute_error = 1;

	int i, j, k, l;

	int id_datacube_out = ((OPH_SPLIT_operator_handle *) handle->operator_handle)->id_output_datacube;
	int id_datacube_in = ((OPH_SPLIT_operator_handle *) handle->operator_handle)->id_input_datacube;

	oph_odb_fragment_list frags;
	oph_odb_db_instance_list dbs;
	oph_odb_dbms_instance_list dbmss;

	//Each process has to be connected to a slave ophidiadb
	ophidiadb oDB_slave;
	oph_odb_init_ophidiadb(&oDB_slave);

	if (oph_odb_read_ophidiadb_config_file(&oDB_slave)) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to read OphidiaDB configuration\n");
		logging(LOG_ERROR, __FILE__, __LINE__, ((OPH_SPLIT_operator_handle *) handle->operator_handle)->id_input_container, OPH_LOG_OPH_SPLIT_OPHIDIADB_CONFIGURATION_FILE);
		return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
	}

	if (oph_odb_connect_to_ophidiadb(&oDB_slave)) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to connect to OphidiaDB. Check access parameters.\n");
		logging(LOG_ERROR, __FILE__, __LINE__, ((OPH_SPLIT_operator_handle *) handle->operator_handle)->id_input_container, OPH_LOG_OPH_SPLIT_OPHIDIADB_CONNECTION_ERROR);
		oph_odb_free_ophidiadb(&oDB_slave);
		return OPH_ANALYTICS_OPERATOR_MYSQL_ERROR;
	}
	//retrieve connection string
	if (oph_odb_stge_fetch_fragment_connection_string(&oDB_slave, id_datacube_in, ((OPH_SPLIT_operator_handle *) handle->operator_handle)->fragment_ids, &frags, &dbs, &dbmss)) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to retreive connection strings\n");
		logging(LOG_ERROR, __FILE__, __LINE__, ((OPH_SPLIT_operator_handle *) handle->operator_handle)->id_input_container, OPH_LOG_OPH_SPLIT_CONNECTION_STRINGS_NOT_FOUND);
		oph_odb_free_ophidiadb(&oDB_slave);
		return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
	}
	//char insertQuery[OPH_COMMON_BUFFER_LEN];
	char frag_name_in[1 + OPH_ODB_STGE_FRAG_NAME_SIZE], frag_name_out[OPH_ODB_STGE_FRAG_NAME_SIZE];
	char myquery[OPH_COMMON_BUFFER_LEN];
	int n, txfrag;

	int frag_count = 0;
	int tuple_count = 0;
	int start_index, key_start, tuplexfragment, new_tuplexfragment, new_remainder;
	int result = OPH_ANALYTICS_OPERATOR_SUCCESS;


	if (oph_dc_setup_dbms(&(((OPH_SPLIT_operator_handle *) handle->operator_handle)->server), (dbmss.value[0]).io_server_type)) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to initialize IO server.\n");
		logging(LOG_ERROR, __FILE__, __LINE__, ((OPH_SPLIT_operator_handle *) handle->operator_handle)->id_input_container, OPH_LOG_OPH_SPLIT_IOPLUGIN_SETUP_ERROR, (dbmss.value[0]).id_dbms);
		result = OPH_ANALYTICS_OPERATOR_MYSQL_ERROR;
	}
	//For each DBMS
	for (i = 0; (i < dbmss.size) && (result == OPH_ANALYTICS_OPERATOR_SUCCESS); i++) {

		if (oph_dc_connect_to_dbms(((OPH_SPLIT_operator_handle *) handle->operator_handle)->server, &(dbmss.value[i]), 0)) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to connect to DBMS. Check access parameters.\n");
			logging(LOG_ERROR, __FILE__, __LINE__, ((OPH_SPLIT_operator_handle *) handle->operator_handle)->id_input_container, OPH_LOG_OPH_SPLIT_DBMS_CONNECTION_ERROR, "output",
				(dbmss.value[i]).id_dbms);
			result = OPH_ANALYTICS_OPERATOR_MYSQL_ERROR;
		}
		//For each DB
		for (j = 0; (j < dbs.size) && (result == OPH_ANALYTICS_OPERATOR_SUCCESS); j++) {
			//Check DB - DBMS Association
			if (dbs.value[j].dbms_instance != &(dbmss.value[i]))
				continue;

			if (oph_dc_use_db_of_dbms(((OPH_SPLIT_operator_handle *) handle->operator_handle)->server, &(dbmss.value[i]), &(dbs.value[j]))) {
				pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to use the DB. Check access parameters.\n");
				logging(LOG_ERROR, __FILE__, __LINE__, ((OPH_SPLIT_operator_handle *) handle->operator_handle)->id_input_container, OPH_LOG_OPH_SPLIT_DB_SELECTION_ERROR, "output",
					(dbs.value[j]).db_name);
				result = OPH_ANALYTICS_OPERATOR_MYSQL_ERROR;
				break;
			}
			//For each fragment
			for (k = 0; (k < frags.size) && (result == OPH_ANALYTICS_OPERATOR_SUCCESS); k++) {
				//Check Fragment - DB Association
				if (frags.value[k].db_instance != &(dbs.value[j]))
					continue;

				//Store the name of fragment I'm going to split
				strncpy(frag_name_in, frags.value[k].fragment_name, OPH_ODB_STGE_FRAG_NAME_SIZE);
				frag_name_in[OPH_ODB_STGE_FRAG_NAME_SIZE] = 0;
				tuple_count = 0;

				start_index = frags.value[k].frag_relative_index;
				key_start = frags.value[k].key_start;
				if (key_start) {
					tuplexfragment = frags.value[k].key_end - key_start + 1;
					new_tuplexfragment = tuplexfragment / ((OPH_SPLIT_operator_handle *) handle->operator_handle)->split_number;
					new_remainder = tuplexfragment % ((OPH_SPLIT_operator_handle *) handle->operator_handle)->split_number;
				} else
					new_tuplexfragment = new_remainder = 0;

				for (l = 0; (l < ((OPH_SPLIT_operator_handle *) handle->operator_handle)->split_number) && (result == OPH_ANALYTICS_OPERATOR_SUCCESS); l++) {

					if (oph_dc_generate_fragment_name(NULL, id_datacube_out, handle->proc_rank, (frag_count + 1), &frag_name_out)) {
						pmesg(LOG_ERROR, __FILE__, __LINE__, "Size of frag  name exceed limit.\n");
						logging(LOG_ERROR, __FILE__, __LINE__, ((OPH_SPLIT_operator_handle *) handle->operator_handle)->id_input_container,
							OPH_LOG_OPH_SPLIT_STRING_BUFFER_OVERFLOW, "fragment name", frag_name_out);
						result = OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
						break;
					}
					//Write new fragment
					//Check if I have to add one more tuple in fragment
					if ((((OPH_SPLIT_operator_handle *) handle->operator_handle)->split_number - new_remainder) <= l)
						txfrag = new_tuplexfragment + 1;
					else
						txfrag = new_tuplexfragment;
#ifdef OPH_DEBUG_MYSQL
					printf("ORIGINAL QUERY: " OPH_SPLIT_QUERY_MYSQL "\n", frag_name_out, MYSQL_FRAG_ID, MYSQL_FRAG_MEASURE, MYSQL_FRAG_ID, MYSQL_FRAG_MEASURE, frag_name_in,
					       MYSQL_FRAG_ID, tuple_count, txfrag);
#endif

					n = snprintf(myquery, OPH_COMMON_BUFFER_LEN, OPH_SPLIT_QUERY, frag_name_out, MYSQL_FRAG_ID, MYSQL_FRAG_MEASURE, frag_name_in, MYSQL_FRAG_ID, tuple_count,
						     txfrag);
					if (n >= OPH_COMMON_BUFFER_LEN) {
						pmesg(LOG_ERROR, __FILE__, __LINE__, "Size of frag  name exceed limit.\n");
						logging(LOG_ERROR, __FILE__, __LINE__, ((OPH_SPLIT_operator_handle *) handle->operator_handle)->id_input_container,
							OPH_LOG_OPH_SPLIT_STRING_BUFFER_OVERFLOW, "MySQL operation name", myquery);
						result = OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
						break;
					}
					if (oph_dc_create_fragment_from_query(((OPH_SPLIT_operator_handle *) handle->operator_handle)->server, &(frags.value[k]), NULL, myquery, 0, 0, 0)) {
						pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to insert new fragment.\n");
						logging(LOG_ERROR, __FILE__, __LINE__, ((OPH_SPLIT_operator_handle *) handle->operator_handle)->id_input_container, OPH_LOG_OPH_SPLIT_NEW_FRAG_ERROR,
							frag_name_out);
						result = OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
						break;
					}
					//Change fragment fields
					frags.value[k].id_datacube = id_datacube_out;
					strncpy(frags.value[k].fragment_name, frag_name_out, OPH_ODB_STGE_FRAG_NAME_SIZE);
					frags.value[k].fragment_name[OPH_ODB_STGE_FRAG_NAME_SIZE] = 0;
					frags.value[k].frag_relative_index = (start_index - 1) * ((OPH_SPLIT_operator_handle *) handle->operator_handle)->split_number + l + 1;
					if (key_start) {
						if (l)
							frags.value[k].key_start = key_start + tuple_count;
						frags.value[k].key_end = key_start + tuple_count + txfrag - 1;
					}
					//Insert new fragment
					if (oph_odb_stge_insert_into_fragment_table(&oDB_slave, &(frags.value[k]))) {
						pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to update fragment table.\n");
						logging(LOG_ERROR, __FILE__, __LINE__, ((OPH_SPLIT_operator_handle *) handle->operator_handle)->id_input_container,
							OPH_LOG_OPH_SPLIT_FRAGMENT_INSERT_ERROR, frag_name_out);
						result = OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
						break;
					}
					frag_count++;
					tuple_count += txfrag;
				}
			}
		}
		oph_dc_disconnect_from_dbms(((OPH_SPLIT_operator_handle *) handle->operator_handle)->server, &(dbmss.value[i]));
	}

	if (oph_dc_cleanup_dbms(((OPH_SPLIT_operator_handle *) handle->operator_handle)->server)) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to finalize IO server.\n");
		logging(LOG_ERROR, __FILE__, __LINE__, ((OPH_SPLIT_operator_handle *) handle->operator_handle)->id_input_container, OPH_LOG_OPH_SPLIT_IOPLUGIN_CLEANUP_ERROR, (dbmss.value[0]).id_dbms);
		result = OPH_ANALYTICS_OPERATOR_MYSQL_ERROR;
	}

	oph_odb_free_ophidiadb(&oDB_slave);
	oph_odb_stge_free_fragment_list(&frags);
	oph_odb_stge_free_db_list(&dbs);
	oph_odb_stge_free_dbms_list(&dbmss);

	if (handle->proc_rank == 0 && (result == OPH_ANALYTICS_OPERATOR_SUCCESS)) {
		//Master process print output datacube PID
		char *tmp_uri = NULL;
		if (oph_pid_get_uri(&tmp_uri)) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to retrieve web server URI.\n");
			logging(LOG_WARNING, __FILE__, __LINE__, ((OPH_SPLIT_operator_handle *) handle->operator_handle)->id_input_container, OPH_LOG_OPH_SPLIT_PID_URI_ERROR);
			return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
		}
		if (oph_pid_show_pid
		    (((OPH_SPLIT_operator_handle *) handle->operator_handle)->id_output_container, ((OPH_SPLIT_operator_handle *) handle->operator_handle)->id_output_datacube, tmp_uri)) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to print PID string\n");
			logging(LOG_WARNING, __FILE__, __LINE__, ((OPH_SPLIT_operator_handle *) handle->operator_handle)->id_input_container, OPH_LOG_OPH_SPLIT_PID_SHOW_ERROR);
			free(tmp_uri);
			return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
		}

		char jsonbuf[OPH_COMMON_BUFFER_LEN];
		memset(jsonbuf, 0, OPH_COMMON_BUFFER_LEN);
		snprintf(jsonbuf, OPH_COMMON_BUFFER_LEN, OPH_PID_FORMAT, tmp_uri, ((OPH_SPLIT_operator_handle *) handle->operator_handle)->id_output_container,
			 ((OPH_SPLIT_operator_handle *) handle->operator_handle)->id_output_datacube);

		// ADD OUTPUT PID TO JSON AS TEXT
		if (oph_json_is_objkey_printable
		    (((OPH_SPLIT_operator_handle *) handle->operator_handle)->objkeys, ((OPH_SPLIT_operator_handle *) handle->operator_handle)->objkeys_num, OPH_JSON_OBJKEY_SPLIT)) {
			if (oph_json_add_text(handle->operator_json, OPH_JSON_OBJKEY_SPLIT, "Output Cube", jsonbuf)) {
				pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD TEXT error\n");
				logging(LOG_WARNING, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "ADD TEXT error\n");
				free(tmp_uri);
				return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
			}
		}
		// ADD OUTPUT PID TO NOTIFICATION STRING
		char tmp_string[OPH_COMMON_BUFFER_LEN];
		snprintf(tmp_string, OPH_COMMON_BUFFER_LEN, "%s=%s;", OPH_IN_PARAM_DATACUBE_INPUT, jsonbuf);
		if (handle->output_string) {
			strncat(tmp_string, handle->output_string, OPH_COMMON_BUFFER_LEN - strlen(tmp_string));
			free(handle->output_string);
		}
		handle->output_string = strdup(tmp_string);

		free(tmp_uri);
	}

	if (result == OPH_ANALYTICS_OPERATOR_SUCCESS)
		((OPH_SPLIT_operator_handle *) handle->operator_handle)->execute_error = 0;

	return result;
}
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_SCRIPT_NULL_OPERATOR_HANDLE);
		return OPH_ANALYTICS_OPERATOR_NULL_OPERATOR_HANDLE;
	}

	if (((OPH_SCRIPT_operator_handle *) handle->operator_handle)->list
	    && oph_json_is_objkey_printable(((OPH_SCRIPT_operator_handle *) handle->operator_handle)->objkeys, ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->objkeys_num,
					    OPH_JSON_OBJKEY_SCRIPT)) {
		char config[OPH_COMMON_BUFFER_LEN];
		snprintf(config, OPH_COMMON_BUFFER_LEN, OPH_FRAMEWORK_SCRIPT_CONF_FILE_PATH, OPH_ANALYTICS_LOCATION);
		FILE *file = fopen(config, "r");
		if (!file) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "%s: no such file\n", config);
			logging(LOG_ERROR, __FILE__, __LINE__, 0, "%s: no such file\n", config);
			return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
		}

		char **jsonkeys = NULL, **fieldtypes = NULL;
		int num_fields = 1, iii, jjj = 0;
#if defined(OPH_DEBUG_LEVEL_1) || defined(OPH_DEBUG_LEVEL_2)
		num_fields = 2;
#endif
		jsonkeys = (char **) malloc(sizeof(char *) * num_fields);
		if (!jsonkeys) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
			logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_SCRIPT_MEMORY_ERROR_INPUT, "keys");
			return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
		}
		jsonkeys[jjj] = strdup("SCRIPT");
		if (!jsonkeys[jjj]) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
			logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_SCRIPT_MEMORY_ERROR_INPUT, "key");
			for (iii = 0; iii < jjj; iii++)
				if (jsonkeys[iii])
					free(jsonkeys[iii]);
			if (jsonkeys)
				free(jsonkeys);
			return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
		}
#if defined(OPH_DEBUG_LEVEL_1) || defined(OPH_DEBUG_LEVEL_2)
		jjj++;
		jsonkeys[jjj] = strdup("COMMAND");
		if (!jsonkeys[jjj]) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
			logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_SCRIPT_MEMORY_ERROR_INPUT, "key");
			for (iii = 0; iii < jjj; iii++)
				if (jsonkeys[iii])
					free(jsonkeys[iii]);
			if (jsonkeys)
				free(jsonkeys);
			return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
		}
#endif
		jjj = 0;
		fieldtypes = (char **) malloc(sizeof(char *) * num_fields);
		if (!fieldtypes) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
			logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_SCRIPT_MEMORY_ERROR_INPUT, "fieldtypes");
			for (iii = 0; iii < num_fields; iii++)
				if (jsonkeys[iii])
					free(jsonkeys[iii]);
			if (jsonkeys)
				free(jsonkeys);
			return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
		}
		fieldtypes[jjj] = strdup(OPH_JSON_STRING);
		if (!fieldtypes[jjj]) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
			logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_SCRIPT_MEMORY_ERROR_INPUT, "fieldtype");
			for (iii = 0; iii < num_fields; iii++)
				if (jsonkeys[iii])
					free(jsonkeys[iii]);
			if (jsonkeys)
				free(jsonkeys);
			for (iii = 0; iii < jjj; iii++)
				if (fieldtypes[iii])
					free(fieldtypes[iii]);
			if (fieldtypes)
				free(fieldtypes);
			return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
		}
#if defined(OPH_DEBUG_LEVEL_1) || defined(OPH_DEBUG_LEVEL_2)
		jjj++;
		fieldtypes[jjj] = strdup(OPH_JSON_STRING);
		if (!fieldtypes[jjj]) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
			logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_SCRIPT_MEMORY_ERROR_INPUT, "fieldtype");
			for (iii = 0; iii < num_fields; iii++)
				if (jsonkeys[iii])
					free(jsonkeys[iii]);
			if (jsonkeys)
				free(jsonkeys);
			for (iii = 0; iii < jjj; iii++)
				if (fieldtypes[iii])
					free(fieldtypes[iii]);
			if (fieldtypes)
				free(fieldtypes);
			return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
		}
#endif
		jjj++;
		if (oph_json_add_grid(handle->operator_json, OPH_JSON_OBJKEY_SCRIPT, "Available scripts", NULL, jsonkeys, 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");
			for (iii = 0; iii < num_fields; iii++)
				if (jsonkeys[iii])
					free(jsonkeys[iii]);
			if (jsonkeys)
				free(jsonkeys);
			for (iii = 0; iii < num_fields; iii++)
				if (fieldtypes[iii])
					free(fieldtypes[iii]);
			if (fieldtypes)
				free(fieldtypes);
			return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
		}
		for (iii = 0; iii < num_fields; iii++)
			if (jsonkeys[iii])
				free(jsonkeys[iii]);
		if (jsonkeys)
			free(jsonkeys);
		for (iii = 0; iii < num_fields; iii++)
			if (fieldtypes[iii])
				free(fieldtypes[iii]);
		if (fieldtypes)
			free(fieldtypes);

		char script[OPH_COMMON_BUFFER_LEN], *pch, *save_pointer, *key, *value, **jsonvalues;
		while (fgets(script, OPH_COMMON_BUFFER_LEN, file)) {
			save_pointer = NULL;
			key = NULL;
			value = NULL;
			for (pch = strtok_r(script, OPH_SCRIPT_NOP, &save_pointer); pch; pch = strtok_r(NULL, OPH_SCRIPT_NOP, &save_pointer)) {
				if (!key)
					key = pch;
				else if (!value)
					value = pch;
				else
					break;
			}
			if (!key || !strlen(key) || !value || !strlen(value))
				continue;
			if (value[strlen(value) - 1] == '\n')
				value[strlen(value) - 1] = 0;
			if (!strlen(value))
				continue;

			jjj = 0;
			jsonvalues = (char **) calloc(num_fields, sizeof(char *));
			if (!jsonvalues) {
				pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
				logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_SCRIPT_MEMORY_ERROR_INPUT, "values");
				return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
			}
			jsonvalues[jjj] = strdup(key);
			if (!jsonvalues[jjj]) {
				pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
				logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_SCRIPT_MEMORY_ERROR_INPUT, "value");
				for (iii = 0; iii < jjj; iii++)
					if (jsonvalues[iii])
						free(jsonvalues[iii]);
				if (jsonvalues)
					free(jsonvalues);
				return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
			}
#if defined(OPH_DEBUG_LEVEL_1) || defined(OPH_DEBUG_LEVEL_2)
			jjj++;
			jsonvalues[jjj] = strdup(value);
			if (!jsonvalues[jjj]) {
				pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
				logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_SCRIPT_MEMORY_ERROR_INPUT, "value");
				for (iii = 0; iii < jjj; iii++)
					if (jsonvalues[iii])
						free(jsonvalues[iii]);
				if (jsonvalues)
					free(jsonvalues);
				return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
			}
#endif
			jjj++;
			if (oph_json_add_grid_row(handle->operator_json, OPH_JSON_OBJKEY_SCRIPT, jsonvalues)) {
				pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRID ROW error\n");
				logging(LOG_WARNING, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "ADD GRID ROW error\n");
				for (iii = 0; iii < num_fields; iii++)
					if (jsonvalues[iii])
						free(jsonvalues[iii]);
				if (jsonvalues)
					free(jsonvalues);
				return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
			}
			for (iii = 0; iii < num_fields; iii++)
				if (jsonvalues[iii])
					free(jsonvalues[iii]);
			if (jsonvalues)
				free(jsonvalues);
		}
		fclose(file);

		return OPH_ANALYTICS_OPERATOR_SUCCESS;
	}
	//Create dir if not exist
	struct stat st;
	if (stat(((OPH_SCRIPT_operator_handle *) handle->operator_handle)->session_path, &st)) {
		if (oph_dir_r_mkdir(((OPH_SCRIPT_operator_handle *) handle->operator_handle)->session_path)) {
			pmesg(LOG_WARNING, __FILE__, __LINE__, "Unable to create dir %s\n", ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->session_path);
			logging(LOG_WARNING, __FILE__, __LINE__, 0, OPH_LOG_GENERIC_DIR_CREATION_ERROR, ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->session_path);
			free(((OPH_SCRIPT_operator_handle *) handle->operator_handle)->session_path);
			((OPH_SCRIPT_operator_handle *) handle->operator_handle)->session_path = NULL;
			free(((OPH_SCRIPT_operator_handle *) handle->operator_handle)->session_url);
			((OPH_SCRIPT_operator_handle *) handle->operator_handle)->session_url = NULL;
		}
	}

	if (strcmp(((OPH_SCRIPT_operator_handle *) handle->operator_handle)->script, OPH_SCRIPT_NOP)) {
		// Check for registered scripts
		char config[OPH_COMMON_BUFFER_LEN];
		snprintf(config, OPH_COMMON_BUFFER_LEN, OPH_FRAMEWORK_SCRIPT_CONF_FILE_PATH, OPH_ANALYTICS_LOCATION);
		FILE *file = fopen(config, "r");
		if (!file) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "%s: no such file\n", config);
			logging(LOG_ERROR, __FILE__, __LINE__, 0, "%s: no such file\n", config);
			return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
		}
		int found = 0;
		char script[OPH_COMMON_BUFFER_LEN], *pch, *save_pointer, *key, *value;
		while (fgets(script, OPH_COMMON_BUFFER_LEN, file)) {
			save_pointer = NULL;
			key = NULL;
			value = NULL;
			for (pch = strtok_r(script, OPH_SCRIPT_NOP, &save_pointer); pch; pch = strtok_r(NULL, OPH_SCRIPT_NOP, &save_pointer)) {
				if (!key)
					key = pch;
				else if (!value)
					value = pch;
				else
					break;
			}
			if (!key || !strlen(key) || !value || !strlen(value))
				continue;
			if (value[strlen(value) - 1] == '\n')
				value[strlen(value) - 1] = 0;
			if (!strlen(value))
				continue;
			if (!strcmp(((OPH_SCRIPT_operator_handle *) handle->operator_handle)->script, key)) {
				pch = value;
				while (pch && (*pch == ' '))
					pch++;
				if (!pch || !*pch)
					continue;
				else if (*pch != '/') {
					snprintf(config, OPH_COMMON_BUFFER_LEN, OPH_FRAMEWORK_SCRIPT_FOLDER_PATH "/%s", OPH_ANALYTICS_LOCATION, value);
					value = config;
				}

				free(((OPH_SCRIPT_operator_handle *) handle->operator_handle)->script);
				((OPH_SCRIPT_operator_handle *) handle->operator_handle)->script = strdup(value);
				found = 1;
				break;
			}
		}
		fclose(file);

		if (!found) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "%s: no such script\n", ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->script);
			logging(LOG_ERROR, __FILE__, __LINE__, 0, "%s: no such script\n", ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->script);
			return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
		}
		//If script is not a regular file then error
		if (stat(((OPH_SCRIPT_operator_handle *) handle->operator_handle)->script, &st)) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "%s: no such file\n", ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->script);
			logging(LOG_ERROR, __FILE__, __LINE__, 0, "%s: no such file\n", ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->script);
			return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
		}
		char *ptr = realpath(((OPH_SCRIPT_operator_handle *) handle->operator_handle)->script, NULL);
		if (!ptr) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to resolve path\n");
			logging(LOG_ERROR, __FILE__, __LINE__, 0, "Unable to resolve path\n");
			return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
		}
		if (!strncmp(ptr, "/bin/", 5) || !strncmp(ptr, "/sbin/", 6) || !strncmp(ptr, "/usr/bin/", 9) || !strncmp(ptr, "/usr/sbin/", 10)) {
			free(ptr);
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Permission denied\n");
			logging(LOG_ERROR, __FILE__, __LINE__, 0, "Permission denied\n");
			return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
		}
		free(ptr);
	}

	char *base_src_path = NULL;
	if (oph_pid_get_base_src_path(&base_src_path)) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to read OphidiaDB configuration\n");
		logging(LOG_ERROR, __FILE__, __LINE__, 0, "Unable to read OphidiaDB configuration\n");
		return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
	}

	int error = 0, n = 0, i;
	char command[OPH_COMMON_BUFFER_LEN];
	memset(command, 0, OPH_COMMON_BUFFER_LEN);
	n += snprintf(command + n, OPH_COMMON_BUFFER_LEN - n, "OPH_SCRIPT_DATA_PATH='%s' ", base_src_path ? base_src_path : "");
	n += snprintf(command + n, OPH_COMMON_BUFFER_LEN - n, "OPH_SCRIPT_SESSION_PATH='%s' ",
		      ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->session_path ? ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->session_path : "");
	n += snprintf(command + n, OPH_COMMON_BUFFER_LEN - n, "OPH_SCRIPT_SESSION_URL='%s' ",
		      ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->session_url ? ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->session_url : "");
	n += snprintf(command + n, OPH_COMMON_BUFFER_LEN - n, "OPH_SCRIPT_SESSION_CODE='%s' ", ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->session_code);
	n += snprintf(command + n, OPH_COMMON_BUFFER_LEN - n, "OPH_SCRIPT_WORKFLOW_ID=%s ",
		      ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->workflow_id ? ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->workflow_id : 0);
	n += snprintf(command + n, OPH_COMMON_BUFFER_LEN - n, "OPH_SCRIPT_MARKER_ID=%s ",
		      ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->marker_id ? ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->marker_id : 0);
	n += snprintf(command + n, OPH_COMMON_BUFFER_LEN - n, "%s ", ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->script);

	for (i = 0; i < ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->args_num; i++) {
		n += snprintf(command + n, OPH_COMMON_BUFFER_LEN - n, "%s ", ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->args[i]);
	}

	if (strcmp(((OPH_SCRIPT_operator_handle *) handle->operator_handle)->out_redir, "stdout")) {
		n += snprintf(command + n, OPH_COMMON_BUFFER_LEN - n, "1>>%s ", ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->out_redir);
	}
	if (strcmp(((OPH_SCRIPT_operator_handle *) handle->operator_handle)->err_redir, "stderr")) {
		n += snprintf(command + n, OPH_COMMON_BUFFER_LEN - n, "2>>%s", ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->err_redir);
	}
	// Dynamic creation of the folders
	if (((OPH_SCRIPT_operator_handle *) handle->operator_handle)->session_path) {
		char dirname[OPH_COMMON_BUFFER_LEN];
		snprintf(dirname, OPH_COMMON_BUFFER_LEN, "%s/%s", ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->session_path,
			 ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->workflow_id);
		struct stat ss;
		if (stat(dirname, &ss) && (errno == ENOENT)) {
			int i;
			for (i = 0; dirname[i]; ++i) {
				if (dirname[i] == '/') {
					dirname[i] = 0;
					mkdir(dirname, 0755);
					dirname[i] = '/';
				}
			}
			mkdir(dirname, 0755);
		}
	}

	char system_output[MAX_OUT_LEN];
	memset(system_output, 0, MAX_OUT_LEN);
	char line[OPH_COMMON_BUFFER_LEN];
	snprintf(system_output, MAX_OUT_LEN, "Command: %s\n\n", command);

	int s = 0, so = 1;
	FILE *fp = popen(command, "r");
	if (!fp)
		error = -1;
	else {
		while (fgets(line, OPH_COMMON_BUFFER_LEN, fp))
			if ((s = MAX_OUT_LEN - strlen(system_output)) > 1)
				strncat(system_output, line, s);
		error = pclose(fp);
	}

	// ADD COMMAND TO JSON AS TEXT
	s = oph_json_is_objkey_printable(((OPH_SCRIPT_operator_handle *) handle->operator_handle)->objkeys, ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->objkeys_num,
					 OPH_JSON_OBJKEY_SCRIPT);
#if defined(OPH_DEBUG_LEVEL_1) || defined(OPH_DEBUG_LEVEL_2)
	if (s && oph_json_add_text(handle->operator_json, OPH_JSON_OBJKEY_SCRIPT, "System output", system_output)) {
		pmesg(LOG_WARNING, __FILE__, __LINE__, "ADD TEXT error\n");
		logging(LOG_WARNING, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "ADD TEXT error\n");
	}
	so = 0;
#endif
	if (((OPH_SCRIPT_operator_handle *) handle->operator_handle)->session_path) {
		if (((OPH_SCRIPT_operator_handle *) handle->operator_handle)->workflow_id)
			snprintf(system_output, MAX_OUT_LEN, "%s/%s", ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->session_url,
				 ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->workflow_id);
		else
			snprintf(system_output, MAX_OUT_LEN, "%s", ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->session_url);
		if (s && oph_json_add_text(handle->operator_json, OPH_JSON_OBJKEY_SCRIPT, "Output URL", system_output)) {
			pmesg(LOG_WARNING, __FILE__, __LINE__, "ADD TEXT error\n");
			logging(LOG_WARNING, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "ADD TEXT error\n");
		}
	} else {
		if (so && s && oph_json_add_text(handle->operator_json, OPH_JSON_OBJKEY_SCRIPT, "SUCCESS", NULL)) {
			pmesg(LOG_WARNING, __FILE__, __LINE__, "ADD TEXT error\n");
			logging(LOG_WARNING, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "ADD TEXT error\n");
		}
	}

	// ADD OUTPUT PID TO NOTIFICATION STRING
	if (((OPH_SCRIPT_operator_handle *) handle->operator_handle)->session_url) {
		char tmp_string[OPH_COMMON_BUFFER_LEN];
		snprintf(tmp_string, OPH_COMMON_BUFFER_LEN, "%s=%s;", OPH_IN_PARAM_LINK, s ? system_output : ((OPH_SCRIPT_operator_handle *) handle->operator_handle)->session_url);
		if (handle->output_string) {
			strncat(tmp_string, handle->output_string, OPH_COMMON_BUFFER_LEN - strlen(tmp_string));
			free(handle->output_string);
		}
		handle->output_string = strdup(tmp_string);
	}

	if (error == -1) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "System command failed\n");
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_SCRIPT_COMMAND_FAILED);
		return OPH_ANALYTICS_OPERATOR_COMMAND_ERROR;
	} else if (WEXITSTATUS(error) == 127) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "System command cannot be executed\n");
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_SCRIPT_COMMAND_NOT_EXECUTED);
		return OPH_ANALYTICS_OPERATOR_COMMAND_ERROR;
	} else if (WEXITSTATUS(error) != 0) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Command failed with code %d\n", WEXITSTATUS(error));
		logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, "Command failed with code %d\n", WEXITSTATUS(error));
		return OPH_ANALYTICS_OPERATOR_COMMAND_ERROR;
	} else
		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_OPERATORS_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_OPERATORS_LIST_INFO_START);

  char *name_filter = ((OPH_OPERATORS_LIST_operator_handle*)handle->operator_handle)->name_filter;
  int limit = ((OPH_OPERATORS_LIST_operator_handle*)handle->operator_handle)->limit;

  char list[1000];
  snprintf(list, sizeof(list), OPH_ANALYTICS_DYNAMIC_LIBRARY_FILE_PATH, OPH_ANALYTICS_LOCATION);
  FILE *file = fopen(list, "r");
  if(file == NULL)
  {
      pmesg(LOG_ERROR, __FILE__, __LINE__, "Drivers list file not found\n");
      logging(LOG_ERROR,__FILE__,__LINE__, OPH_GENERIC_CONTAINER_ID,OPH_LOG_OPH_OPERATORS_LIST_FILE_NOT_FOUND);
      return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
  }

  char buffer[256],operator[30];
  char *position1,*position2;
  char **oplist;
  int i,j,oplist_size=0;

  // get oplist size
  if (limit==0) {
      //no limit
      while (fscanf(file, "%s", buffer) != EOF)
      {
          position1 = strchr(buffer, '[');
          if (position1 != NULL) {
              position2 = strchr(position1+1,']');
              if (position2 == NULL) {
                  pmesg(LOG_ERROR, __FILE__, __LINE__, "Matching closing bracket not found\n");
                  logging(LOG_ERROR,__FILE__,__LINE__, OPH_GENERIC_CONTAINER_ID,OPH_LOG_OPH_OPERATORS_LIST_BRACKET_NOT_FOUND);
                  fclose(file);
			      return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
              }
              strncpy(operator,position1+1,strlen(position1)-strlen(position2)-1);
              operator[strlen(position1)-strlen(position2)-1] = 0;

              if (name_filter==NULL) {
                  oplist_size++;
              } else {
                  if (strcasestr(operator,name_filter)) {
                      oplist_size++;
                  }
              }
          }
      }
  } else {
      int count=0;
      while (fscanf(file, "%s", buffer) != EOF && count < limit)
      {
          position1 = strchr(buffer, '[');
          if (position1 != NULL) {
              position2 = strchr(position1+1,']');
              if (position2 == NULL) {
                  pmesg(LOG_ERROR, __FILE__, __LINE__, "Matching closing bracket not found\n");
                  logging(LOG_ERROR,__FILE__,__LINE__, OPH_GENERIC_CONTAINER_ID,OPH_LOG_OPH_OPERATORS_LIST_BRACKET_NOT_FOUND);
                  fclose(file);
			      return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
              }
              strncpy(operator,position1+1,strlen(position1)-strlen(position2)-1);
              operator[strlen(position1)-strlen(position2)-1] = 0;

              if (name_filter==NULL) {
                  oplist_size++;
                  count++;
              } else {
                  if (strcasestr(operator,name_filter)) {
                      oplist_size++;
                      count++;
                  }
              }
          }
      }
  }
  fclose(file);

  // alloc oplist
  oplist = (char **)malloc(sizeof(char *)*oplist_size);
  if (!oplist) {
      pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
      logging(LOG_ERROR,__FILE__,__LINE__, OPH_GENERIC_CONTAINER_ID,"Error allocating memory\n");
      return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
  }
  for (i = 0; i < oplist_size; i++) {
      oplist[i] = (char *)malloc(OPH_COMMON_BUFFER_LEN);
      if (!oplist[i]) {
          pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory for path\n");
          for (j = 0; j < i; j++) {
              free(oplist[j]);
          }
          free(oplist);
          return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
      }
  }

  // fill oplist
  int p=0;
  file = fopen(list, "r");
  if(file == NULL)
  {
      pmesg(LOG_ERROR, __FILE__, __LINE__, "Drivers list file not found\n");
      logging(LOG_ERROR,__FILE__,__LINE__, OPH_GENERIC_CONTAINER_ID,OPH_LOG_OPH_OPERATORS_LIST_FILE_NOT_FOUND);
      for (i = 0; i < oplist_size; i++) {
          free(oplist[i]);
      }
      free(oplist);
      return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
  }

  if (limit==0) {
      //no limit
      while (fscanf(file, "%s", buffer) != EOF)
      {
          position1 = strchr(buffer, '[');
          if (position1 != NULL) {
              position2 = strchr(position1+1,']');
              if (position2 == NULL) {
                  pmesg(LOG_ERROR, __FILE__, __LINE__, "Matching closing bracket not found\n");
                  logging(LOG_ERROR,__FILE__,__LINE__, OPH_GENERIC_CONTAINER_ID,OPH_LOG_OPH_OPERATORS_LIST_BRACKET_NOT_FOUND);
                  fclose(file);
                  for (i = 0; i < oplist_size; i++) {
                      free(oplist[i]);
                  }
                  free(oplist);
			      return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
              }
              strncpy(operator,position1+1,strlen(position1)-strlen(position2)-1);
              operator[strlen(position1)-strlen(position2)-1] = 0;

              if (name_filter==NULL) {
                  strncpy(oplist[p],operator,strlen(operator));
                  oplist[p][strlen(operator)] = 0;
                  p++;
              } else {
                  if (strcasestr(operator,name_filter)) {
                      strncpy(oplist[p],operator,strlen(operator));
                      oplist[p][strlen(operator)] = 0;
                      p++;
                  }
              }
          }
      }
  } else {
      int count=0;
      while (fscanf(file, "%s", buffer) != EOF && count < limit)
      {
          position1 = strchr(buffer, '[');
          if (position1 != NULL) {
              position2 = strchr(position1+1,']');
              if (position2 == NULL) {
                  pmesg(LOG_ERROR, __FILE__, __LINE__, "Matching closing bracket not found\n");
                  logging(LOG_ERROR,__FILE__,__LINE__, OPH_GENERIC_CONTAINER_ID,OPH_LOG_OPH_OPERATORS_LIST_BRACKET_NOT_FOUND);
                  fclose(file);
                  for (i = 0; i < oplist_size; i++) {
                      free(oplist[i]);
                  }
                  free(oplist);
			      return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
              }
              strncpy(operator,position1+1,strlen(position1)-strlen(position2)-1);
              operator[strlen(position1)-strlen(position2)-1] = 0;

              if (name_filter==NULL) {
                  strncpy(oplist[p],operator,strlen(operator));
                  oplist[p][strlen(operator)] = 0;
                  p++;
                  count++;
              } else {
                  if (strcasestr(operator,name_filter)) {
                      strncpy(oplist[p],operator,strlen(operator));
                      oplist[p][strlen(operator)] = 0;
                      p++;
                      count++;
                  }
              }
          }
      }
  }
  fclose(file);

  // sort oplist
  qsort(oplist,oplist_size,sizeof(char*),strcmp2);

  printf("+-----------------------------+\n");
  printf("|          OPERATORS          |\n");
  printf("+-----------------------------+\n");

  for (i = 0; i < oplist_size; i++) {
      printf("| %-27s |\n",oplist[i]);
  }

  printf("+-----------------------------+\n");

	int is_objkey_printable = oph_json_is_objkey_printable(((OPH_OPERATORS_LIST_operator_handle*)handle->operator_handle)->objkeys,((OPH_OPERATORS_LIST_operator_handle*)handle->operator_handle)->objkeys_num,OPH_JSON_OBJKEY_OPERATORS_LIST_LIST);
	if (is_objkey_printable)
	{
		// Header
		  char **jsonkeys = NULL;
		  char **fieldtypes = NULL;
		  int num_fields = 1, iii,jjj=0;
		  jsonkeys = (char **)malloc(sizeof(char *)*num_fields);
		  if (!jsonkeys) {
			  pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
			  logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_OPERATORS_LIST_MEMORY_ERROR_INPUT, "keys" );
			  for (i = 0; i < oplist_size; i++) free(oplist[i]);
			  free(oplist);
			  return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
		  }
		  jsonkeys[jjj] = strdup("OPERATORS");
		  if (!jsonkeys[jjj]) {
			  pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
			  logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_OPERATORS_LIST_MEMORY_ERROR_INPUT, "key" );
			  for (iii=0;iii<jjj;iii++) if (jsonkeys[iii]) free(jsonkeys[iii]);
			  if (jsonkeys) free(jsonkeys);
			  for (i = 0; i < oplist_size; i++) free(oplist[i]);
			  free(oplist);
			  return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
		  }
		  jjj = 0;
		  fieldtypes = (char **)malloc(sizeof(char *)*num_fields);
		  if (!fieldtypes) {
			  pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
			  logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_OPERATORS_LIST_MEMORY_ERROR_INPUT, "fieldtypes" );
			  for (iii = 0; iii < num_fields; iii++) if (jsonkeys[iii]) free(jsonkeys[iii]);
			  if (jsonkeys) free(jsonkeys);
			  for (i = 0; i < oplist_size; i++) free(oplist[i]);
			  free(oplist);
			  return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
		  }
		  fieldtypes[jjj] = strdup(OPH_JSON_STRING);
		  if (!fieldtypes[jjj]) {
			  pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
			  logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_OPERATORS_LIST_MEMORY_ERROR_INPUT, "fieldtype" );
			  for (iii = 0; iii < num_fields; iii++) if (jsonkeys[iii]) free(jsonkeys[iii]);
			  if (jsonkeys) free(jsonkeys);
			  for (iii = 0; iii < jjj; iii++) if (fieldtypes[iii]) free(fieldtypes[iii]);
			  if (fieldtypes) free(fieldtypes);
			  for (i = 0; i < oplist_size; i++) free(oplist[i]);
			  free(oplist);
			  return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
		  }
		  if (oph_json_add_grid(handle->operator_json,OPH_JSON_OBJKEY_OPERATORS_LIST_LIST,"Operators List",NULL,jsonkeys,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");
			  for (iii = 0; iii < num_fields; iii++) if (jsonkeys[iii]) free(jsonkeys[iii]);
			  if (jsonkeys) free(jsonkeys);
			  for (iii = 0; iii < num_fields; iii++) if (fieldtypes[iii]) free(fieldtypes[iii]);
			  if (fieldtypes) free(fieldtypes);
			  for (i = 0; i < oplist_size; i++) free(oplist[i]);
			  free(oplist);
			  return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
		  }
		  for (iii = 0; iii < num_fields; iii++) if (jsonkeys[iii]) free(jsonkeys[iii]);
		  if (jsonkeys) free(jsonkeys);
		  for (iii = 0; iii < num_fields; iii++) if (fieldtypes[iii]) free(fieldtypes[iii]);
		  if (fieldtypes) free(fieldtypes);

		// Data
		  char **jsonvalues = NULL;
		  jsonvalues = (char **)calloc(num_fields,sizeof(char *));
		  if (!jsonvalues) {
			  pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
			  logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_OPERATORS_LIST_MEMORY_ERROR_INPUT, "values" );
			  for (i = 0; i < oplist_size; i++) free(oplist[i]);
			  free(oplist);
			  return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
		  }
		  for (i = 0; i < oplist_size; i++)
		  {
			  for (jjj = 0; jjj < num_fields; jjj++)
			  {
				  jsonvalues[jjj] = strdup(oplist[i]);
				  if (!jsonvalues[jjj]) {
					  pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
					  logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_OPERATORS_LIST_MEMORY_ERROR_INPUT, "value" );
					  for (iii = 0; iii < jjj; iii++) if (jsonvalues[iii]) free(jsonvalues[iii]);
					  if (jsonvalues) free(jsonvalues);
					  for (i = 0; i < oplist_size; i++) free(oplist[i]);
					  free(oplist);
					  return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
				  }
			  }
			  if (oph_json_add_grid_row(handle->operator_json,OPH_JSON_OBJKEY_OPERATORS_LIST_LIST,jsonvalues)) {
				  pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRID ROW error\n");
				  logging(LOG_WARNING,__FILE__,__LINE__, OPH_GENERIC_CONTAINER_ID,"ADD GRID ROW error\n");
				  for (iii = 0; iii < num_fields; iii++) if (jsonvalues[iii]) free(jsonvalues[iii]);
				  if (jsonvalues) free(jsonvalues);
				  for (i = 0; i < oplist_size; i++) free(oplist[i]);
				  free(oplist);
				  return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
			  }
			  for (iii = 0; iii < num_fields; iii++) if (jsonvalues[iii]) free(jsonvalues[iii]);
		  }
		  if (jsonvalues) free(jsonvalues);
	}

  for (i = 0; i < oplist_size; i++) free(oplist[i]);
  free(oplist);

  printf(OPH_OPERATORS_LIST_HELP_MESSAGE);
	if (oph_json_is_objkey_printable(((OPH_OPERATORS_LIST_operator_handle*)handle->operator_handle)->objkeys,((OPH_OPERATORS_LIST_operator_handle*)handle->operator_handle)->objkeys_num,OPH_JSON_OBJKEY_OPERATORS_LIST_TIP))
	{
		if (oph_json_add_text(handle->operator_json,OPH_JSON_OBJKEY_OPERATORS_LIST_TIP,"Help Message",OPH_OPERATORS_LIST_HELP_MESSAGE))
		{
			pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD TEXT error\n");
			logging(LOG_WARNING,__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_OPERATORS_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_CUBEIO_operator_handle *) handle->operator_handle)->id_input_container, OPH_LOG_OPH_CUBEIO_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_CUBEIO_operator_handle *) handle->operator_handle)->oDB;
	int direction = ((OPH_CUBEIO_operator_handle *) handle->operator_handle)->direction;
	char *datacube_name = ((OPH_CUBEIO_operator_handle *) handle->operator_handle)->datacube_name;
	char **objkeys = ((OPH_CUBEIO_operator_handle *) handle->operator_handle)->objkeys;
	int objkeys_num = ((OPH_CUBEIO_operator_handle *) handle->operator_handle)->objkeys_num;

	char operation[OPH_ODB_CUBE_OPERATOR_SIZE];
	memset(operation, 0, OPH_ODB_CUBE_OPERATOR_SIZE);
	char parentcube_name[OPH_COMMON_BUFFER_LEN];
	memset(parentcube_name, 0, OPH_COMMON_BUFFER_LEN);
	int *type = (int *) malloc(sizeof(int));
	type[0] = 0;

	oph_odb_datacube cube;
	oph_odb_cube_init_datacube(&cube);

	//retrieve input datacube
	if (oph_odb_cube_retrieve_datacube(oDB, ((OPH_CUBEIO_operator_handle *) handle->operator_handle)->id_input_datacube, &cube)) {
		oph_odb_cube_free_datacube(&cube);
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Error while retrieving input datacube\n");
		logging(LOG_ERROR, __FILE__, __LINE__, ((OPH_CUBEIO_operator_handle *) handle->operator_handle)->id_input_container, OPH_LOG_OPH_CUBEIO_DATACUBE_READ_ERROR);
		return OPH_ANALYTICS_OPERATOR_MYSQL_ERROR;
	}

	char source_buffer[OPH_PID_SIZE];
	char source_buffer_json[OPH_PID_SIZE];
	oph_odb_source src;
	if (cube.id_source) {
		//retrieve input datacube
		if (oph_odb_cube_retrieve_source(oDB, cube.id_source, &src)) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Error while retrieving source name\n");
			logging(LOG_ERROR, __FILE__, __LINE__, ((OPH_CUBEIO_operator_handle *) handle->operator_handle)->id_input_container, OPH_LOG_OPH_CUBEIO_SOURCE_READ_ERROR);
			oph_odb_cube_free_datacube(&cube);
			return OPH_ANALYTICS_OPERATOR_MYSQL_ERROR;
		} else {
			snprintf(source_buffer, OPH_PID_SIZE, "- SOURCE: %s", src.uri);
			snprintf(source_buffer_json, OPH_PID_SIZE, "%s", src.uri);
		}
	} else {
		source_buffer[0] = 0;
		source_buffer_json[0] = 0;
	}

	oph_odb_cube_free_datacube(&cube);

	char *tmp_uri = NULL;
	if (oph_pid_get_uri(&tmp_uri)) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to retrieve web server URI.\n");
		logging(LOG_WARNING, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_CUBEIO_PID_URI_ERROR);
		if (tmp_uri)
			free(tmp_uri);
		return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
	}

	if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_CUBEIO)) {
		int num_fields = 4;
		char *keys[4] = { "INPUT CUBE", "OPERATION", "OUTPUT CUBE", "SOURCE" };
		char *fieldtypes[4] = { "string", "string", "string", "string" };
		if (oph_json_add_grid(handle->operator_json, OPH_JSON_OBJKEY_CUBEIO, "Cube Provenance", NULL, keys, num_fields, fieldtypes, num_fields)) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRID error\n");
			logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_CUBEIO_MEMORY_ERROR, "output grid");
			free(type);
			if (tmp_uri)
				free(tmp_uri);
			return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
		}
	}
	if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_CUBEIO_GRAPH)) {
		int num_fields = 2;
		char *keys[2] = { "PID", "SOURCE" };
		if (oph_json_add_graph(handle->operator_json, OPH_JSON_OBJKEY_CUBEIO_GRAPH, 1, "Cube Provenance Graph", NULL, keys, num_fields)) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRAPH error\n");
			logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_CUBEIO_MEMORY_ERROR, "output graph");
			free(type);
			if (tmp_uri)
				free(tmp_uri);
			return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
		}
	}

	if (direction != OPH_CUBEIO_BRANCH_OUT) {
		//Retrieve upper hierarchy
		if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_CUBEIO_GRAPH)) {
			unsigned int nn, nnn;
			int found = 0;
			for (nn = 0; nn < handle->operator_json->response_num; nn++) {
				if (!strcmp(handle->operator_json->response[nn].objkey, OPH_JSON_OBJKEY_CUBEIO_GRAPH)) {
					for (nnn = 0; nnn < ((oph_json_obj_graph *) (handle->operator_json->response[nn].objcontent))[0].nodevalues_num1; nnn++) {
						if (!strcmp(datacube_name, ((oph_json_obj_graph *) (handle->operator_json->response[nn].objcontent))[0].nodevalues[nnn][0])) {
							found = 1;
							break;
						}
					}
					break;
				}
			}
			char *my_row[2] = { datacube_name, source_buffer_json };
			if (!found) {
				if (oph_json_add_graph_node(handle->operator_json, OPH_JSON_OBJKEY_CUBEIO_GRAPH, my_row)) {
					pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRAPH NODE error\n");
					logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_CUBEIO_MEMORY_ERROR, "output graph node");
					free(type);
					if (tmp_uri)
						free(tmp_uri);
					return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
				}
			}
		}
		if (_oph_cubeio_print_parents
		    (tmp_uri, oDB, 0, ((OPH_CUBEIO_operator_handle *) handle->operator_handle)->id_input_datacube, &type, ((OPH_CUBEIO_operator_handle *) handle->operator_handle)->id_input_container,
		     &operation, handle->operator_json, objkeys, objkeys_num, datacube_name, &parentcube_name)) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Error launching parents search function\n");
			logging(LOG_ERROR, __FILE__, __LINE__, ((OPH_CUBEIO_operator_handle *) handle->operator_handle)->id_input_container, OPH_LOG_OPH_CUBEIO_HIERARCHY_FUNCT_ERROR, "parent",
				datacube_name);
			free(type);
			if (tmp_uri)
				free(tmp_uri);
			return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
		}
		printf("--> %s (%s) %s\n", datacube_name, operation, source_buffer);

		if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_CUBEIO)) {
			char *my_row[4] = { parentcube_name, operation, datacube_name, source_buffer_json };
			if (oph_json_add_grid_row(handle->operator_json, OPH_JSON_OBJKEY_CUBEIO, my_row)) {
				pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRID ROW error\n");
				logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_CUBEIO_MEMORY_ERROR, "output grid row");
				free(type);
				if (tmp_uri)
					free(tmp_uri);
				return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
			}
		}

	}
	if (direction != OPH_CUBEIO_BRANCH_IN) {
		//Retrive lower hierarchy
		if (direction != 0) {
			printf("--> %s (%s) %s\n", datacube_name, "ROOT", source_buffer);
			if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_CUBEIO)) {
				char *my_row[4] = { "", "ROOT", datacube_name, source_buffer_json };
				if (oph_json_add_grid_row(handle->operator_json, OPH_JSON_OBJKEY_CUBEIO, my_row)) {
					pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRID ROW error\n");
					logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_CUBEIO_MEMORY_ERROR, "output grid row");
					free(type);
					if (tmp_uri)
						free(tmp_uri);
					return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
				}
			}
			if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_CUBEIO_GRAPH)) {
				unsigned int nn, nnn;
				int found = 0;
				for (nn = 0; nn < handle->operator_json->response_num; nn++) {
					if (!strcmp(handle->operator_json->response[nn].objkey, OPH_JSON_OBJKEY_CUBEIO_GRAPH)) {
						for (nnn = 0; nnn < ((oph_json_obj_graph *) (handle->operator_json->response[nn].objcontent))[0].nodevalues_num1; nnn++) {
							if (!strcmp(datacube_name, ((oph_json_obj_graph *) (handle->operator_json->response[nn].objcontent))[0].nodevalues[nnn][0])) {
								found = 1;
								break;
							}
						}
						break;
					}
				}
				char *my_row[2] = { datacube_name, source_buffer_json };
				if (!found) {
					if (oph_json_add_graph_node(handle->operator_json, OPH_JSON_OBJKEY_CUBEIO_GRAPH, my_row)) {
						pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRAPH NODE error\n");
						logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_CUBEIO_MEMORY_ERROR, "output graph node");
						free(type);
						if (tmp_uri)
							free(tmp_uri);
						return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
					}
				}
			}
		}
		if (_oph_cubeio_print_children
		    (tmp_uri, oDB, 0, ((OPH_CUBEIO_operator_handle *) handle->operator_handle)->id_input_datacube, &type, ((OPH_CUBEIO_operator_handle *) handle->operator_handle)->id_input_container,
		     handle->operator_json, objkeys, objkeys_num)) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Error launching children search function\n");
			logging(LOG_ERROR, __FILE__, __LINE__, ((OPH_CUBEIO_operator_handle *) handle->operator_handle)->id_input_container, OPH_LOG_OPH_CUBEIO_HIERARCHY_FUNCT_ERROR, "children",
				datacube_name);
			free(type);
			if (tmp_uri)
				free(tmp_uri);
			return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
		}
	}
	if (tmp_uri)
		free(tmp_uri);
	free(type);

	return OPH_ANALYTICS_OPERATOR_SUCCESS;
}
int _oph_cubeio_print_parents(char *uri, ophidiadb * oDB, unsigned int level, int id_datacube_leaf, int **parent_type, int id_container_in, char (*operation)[OPH_ODB_CUBE_OPERATOR_SIZE],
			      oph_json * oper_json, char **objkeys, int objkeys_num, char childcube[OPH_COMMON_BUFFER_LEN], char (*parentcube)[OPH_COMMON_BUFFER_LEN])
{
	if (id_datacube_leaf < 1 || id_container_in < 1 || (*parent_type) == 0 || !oDB || !operation || !childcube || !parentcube) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Null input parameter\n");
		logging(LOG_ERROR, __FILE__, __LINE__, id_container_in, OPH_LOG_OPH_CUBEIO_NULL_FUNCTION_PARAMS_PARENT, id_datacube_leaf);
		return OPH_ANALYTICS_OPERATOR_BAD_PARAMETER;
	}
	level++;

	MYSQL_RES *io_datacubes = NULL;
	int num_rows = 0;
	MYSQL_ROW row;
	unsigned int i, j, length;
	int *new_type = NULL;
	int kk = 0;

	if (oph_odb_cube_find_datacube_hierarchy(oDB, 1, id_datacube_leaf, &io_datacubes)) {
		pmesg(LOG_WARNING, __FILE__, __LINE__, "Unable to retreive information of input output datacubes\n");
		logging(LOG_WARNING, __FILE__, __LINE__, id_container_in, OPH_LOG_OPH_CUBEIO_IO_DATACUBE_READ_ERROR, id_datacube_leaf);
		mysql_free_result(io_datacubes);
		//Prepare operation for root element
		length = strlen("ROOT") + 1;
		strncpy(*operation, "ROOT", length);
		(*operation)[length] = '\0';
		snprintf(*parentcube, OPH_COMMON_BUFFER_LEN, "%s", "");
		return OPH_ANALYTICS_OPERATOR_SUCCESS;
	}

	char parent_operation[OPH_ODB_CUBE_OPERATOR_SIZE];
	memset(parent_operation, 0, OPH_ODB_CUBE_OPERATOR_SIZE);
	char parent_parentcube[OPH_COMMON_BUFFER_LEN];
	memset(parent_parentcube, 0, OPH_COMMON_BUFFER_LEN);
	char source_buffer[OPH_PID_SIZE];
	char source_buffer_json[OPH_PID_SIZE];

	//Empty set
	if (!(num_rows = mysql_num_rows(io_datacubes))) {
		pmesg(LOG_WARNING, __FILE__, __LINE__, "No rows find by query\n");
		logging(LOG_WARNING, __FILE__, __LINE__, id_container_in, OPH_LOG_OPH_CUBEIO_NO_ROWS_FOUND);
		//Prepare operation for root element
		length = strlen("ROOT") + 1;
		strncpy(*operation, "ROOT", length);
		(*operation)[length] = '\0';
		snprintf(*parentcube, OPH_COMMON_BUFFER_LEN, "%s", "");
	} else {
		if (mysql_field_count(oDB->conn) != 4) {
			pmesg(LOG_WARNING, __FILE__, __LINE__, "No rows find by query\n");
			logging(LOG_WARNING, __FILE__, __LINE__, id_container_in, OPH_LOG_OPH_CUBEIO_NO_ROWS_FOUND);
			mysql_free_result(io_datacubes);
			return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
		}
		i = 0;
		char *pid;
		int ii = 0;

		while ((row = mysql_fetch_row(io_datacubes))) {
			new_type = (int *) realloc(*parent_type, (level + 1) * sizeof(int));
			if (!new_type) {
				pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
				logging(LOG_ERROR, __FILE__, __LINE__, id_container_in, OPH_LOG_OPH_CUBEIO_MEMORY_ERROR, "parent_type array");
				mysql_free_result(io_datacubes);
				return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
			} else {
				*parent_type = new_type;
			}
			(*parent_type)[level] = i;

			if (uri && row[0] && row[2]) {
				if (oph_pid_create_pid(uri, (int) strtol(row[0], NULL, 10), (int) strtol(row[2], NULL, 10), &pid)) {
					pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to create PID string\n");
					if (pid)
						free(pid);
					pid = NULL;
				}
			}
			//Prepare operation for children elements
			length = (strlen(row[1]) >= (OPH_ODB_CUBE_OPERATOR_SIZE - 1) ? OPH_ODB_CUBE_OPERATOR_SIZE : strlen(row[1]) + 1);
			strncpy(*operation, (row[1] ? row[1] : "-"), length);
			(*operation)[length] = '\0';

			if (row[3]) {
				snprintf(source_buffer, OPH_PID_SIZE, "- SOURCE: %s", row[3]);
				snprintf(source_buffer_json, OPH_PID_SIZE, "%s", row[3]);
			} else {
				source_buffer[0] = 0;
				source_buffer_json[0] = 0;
			}

			if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_CUBEIO_GRAPH)) {
				unsigned int nn, nnn;
				int found = 0;
				for (nn = 0; nn < oper_json->response_num; nn++) {
					if (!strcmp(oper_json->response[nn].objkey, OPH_JSON_OBJKEY_CUBEIO_GRAPH)) {
						for (nnn = 0; nnn < ((oph_json_obj_graph *) (oper_json->response[nn].objcontent))[0].nodevalues_num1; nnn++) {
							if (!strcmp((pid ? pid : ""), ((oph_json_obj_graph *) (oper_json->response[nn].objcontent))[0].nodevalues[nnn][0])) {
								found = 1;
								break;
							}
						}
						break;
					}
				}
				char *my_row[2] = { (pid ? pid : ""), source_buffer_json };
				if (!found) {
					if (oph_json_add_graph_node(oper_json, OPH_JSON_OBJKEY_CUBEIO_GRAPH, my_row)) {
						pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRAPH NODE error\n");
						logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_CUBEIO_MEMORY_ERROR, "output graph node");
						mysql_free_result(io_datacubes);
						if (pid)
							free(pid);
						return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
					}
				}

				int node1 = -1, node2 = -1;
				for (nn = 0; nn < oper_json->response_num; nn++) {

					if (!strcmp(oper_json->response[nn].objkey, OPH_JSON_OBJKEY_CUBEIO_GRAPH)) {
						for (nnn = 0; nnn < ((oph_json_obj_graph *) (oper_json->response[nn].objcontent))[0].nodevalues_num1; nnn++) {
							if (node1 != -1 && node2 != -1)
								break;
							if (!strcmp((pid ? pid : ""), ((oph_json_obj_graph *) (oper_json->response[nn].objcontent))[0].nodevalues[nnn][0]))
								node1 = nnn;
							else if (!strcmp(childcube, ((oph_json_obj_graph *) (oper_json->response[nn].objcontent))[0].nodevalues[nnn][0]))
								node2 = nnn;
						}
						break;
					}
				}

				int node_link = 0;
				found = 0;
				for (nn = 0; nn < oper_json->response_num; nn++) {
					if (!strcmp(oper_json->response[nn].objkey, OPH_JSON_OBJKEY_CUBEIO_GRAPH)) {
						for (nnn = 0; nnn < ((oph_json_obj_graph *) oper_json->response[nn].objcontent)[0].nodelinks[node1].links_num; nnn++) {
							node_link = (int) strtol(((oph_json_obj_graph *) oper_json->response[nn].objcontent)[0].nodelinks[node1].links[nnn].node, NULL, 10);
							if (node_link == node2) {
								found = 1;
								break;
							}
						}
						if (found == 1)
							break;
					}
				}
				if (!found) {
					if (oph_json_add_graph_link(oper_json, OPH_JSON_OBJKEY_CUBEIO_GRAPH, node1, node2, (const char *) operation)) {
						pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRAPH LINK error\n");
						logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_CUBEIO_MEMORY_ERROR, "output graph link");
						mysql_free_result(io_datacubes);
						if (pid)
							free(pid);
						return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
					}
				}
			}

			if (_oph_cubeio_print_parents
			    (uri, oDB, level, (int) strtol(row[2], NULL, 10), parent_type, id_container_in, &parent_operation, oper_json, objkeys, objkeys_num, pid, &parent_parentcube))
				break;

			ii++;
			if (ii == num_rows)
				kk += snprintf((*parentcube) + kk, OPH_COMMON_BUFFER_LEN - kk, "%s", (pid ? pid : ""));
			else
				kk += snprintf((*parentcube) + kk, OPH_COMMON_BUFFER_LEN - kk, "%s - ", (pid ? pid : ""));

			//Shift output string proportionally to its level
			for (j = 1; j < level; j++) {
				if ((*parent_type)[j]) {
					printf(" │   ");
				} else {
					printf("     ");
				}
			}

			//If first element of tree
			if (!i) {
				printf(" ┌─ %s (%s) %s\n", (pid ? pid : "-"), parent_operation, source_buffer);
			} else {
				printf(" ├─ %s (%s) %s\n", (pid ? pid : "-"), parent_operation, source_buffer);
			}
			i++;

			if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_CUBEIO)) {
				char *my_row[4] = { parent_parentcube, parent_operation, (pid ? pid : ""), source_buffer_json };
				if (oph_json_add_grid_row(oper_json, OPH_JSON_OBJKEY_CUBEIO, my_row)) {
					pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRID ROW error\n");
					logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_CUBEIO_MEMORY_ERROR, "output grid row");
					mysql_free_result(io_datacubes);
					if (pid)
						free(pid);
					return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
				}
			}


			if (pid)
				free(pid);
			pid = NULL;
		}
	}
	mysql_free_result(io_datacubes);
	return OPH_ANALYTICS_OPERATOR_SUCCESS;
}
int _oph_cubeio_print_children(char *uri, ophidiadb * oDB, unsigned int level, int id_datacube_root, int **child_type, int id_container_in, oph_json * oper_json, char **objkeys, int objkeys_num)
{
	if (id_datacube_root < 1 || id_container_in < 1 || (*child_type) == NULL || !oDB) {
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Null input parameter\n");
		logging(LOG_ERROR, __FILE__, __LINE__, id_container_in, OPH_LOG_OPH_CUBEIO_NULL_FUNCTION_PARAMS_CHILD, id_datacube_root);
		return OPH_ANALYTICS_OPERATOR_BAD_PARAMETER;
	}
	level++;

	MYSQL_RES *io_datacubes = NULL;
	int num_rows = 0;
	MYSQL_ROW row;
	unsigned int i, j;
	int *new_type = NULL;
	char source_buffer[OPH_PID_SIZE];
	char source_buffer_json[OPH_PID_SIZE];

	if (oph_odb_cube_find_datacube_hierarchy(oDB, 0, id_datacube_root, &io_datacubes)) {
		pmesg(LOG_WARNING, __FILE__, __LINE__, "Unable to retreive information of input output datacubes\n");
		logging(LOG_WARNING, __FILE__, __LINE__, id_container_in, OPH_LOG_OPH_CUBEIO_IO_DATACUBE_READ_ERROR, id_datacube_root);
		mysql_free_result(io_datacubes);
		return OPH_ANALYTICS_OPERATOR_SUCCESS;
	}
	//Empty set
	if (!(num_rows = mysql_num_rows(io_datacubes))) {
		logging(LOG_WARNING, __FILE__, __LINE__, id_container_in, OPH_LOG_OPH_CUBEIO_NO_ROWS_FOUND);
	} else {
		if (mysql_field_count(oDB->conn) != 4) {
			pmesg(LOG_WARNING, __FILE__, __LINE__, "No enough fields found by query\n");
			logging(LOG_WARNING, __FILE__, __LINE__, id_container_in, OPH_LOG_OPH_CUBEIO_NO_ROWS_FOUND);
			mysql_free_result(io_datacubes);
			return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
		}

		i = num_rows - 1;
		char *pid = NULL;
		char *pid2 = NULL;	//root name
		if (uri) {
			if (oph_pid_create_pid(uri, id_container_in, id_datacube_root, &pid2)) {
				pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to create PID string\n");
				if (pid2)
					free(pid2);
				pid2 = NULL;
			}
		}

		while ((row = mysql_fetch_row(io_datacubes))) {
			new_type = (int *) realloc(*child_type, (level + 1) * sizeof(int));
			if (!new_type) {
				pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
				logging(LOG_ERROR, __FILE__, __LINE__, id_container_in, OPH_LOG_OPH_CUBEIO_MEMORY_ERROR, "child_type array");
				mysql_free_result(io_datacubes);
				if (pid2)
					free(pid2);
				pid2 = NULL;
				return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
			} else {
				*child_type = new_type;
			}
			(*child_type)[level] = i;

			//Shift output string proportionally to its level
			for (j = 1; j < level; j++) {
				if ((*child_type)[j]) {
					printf(" │   ");
				} else {
					printf("     ");
				}
			}

			if (uri && row[0] && row[2]) {
				if (oph_pid_create_pid(uri, (int) strtol(row[0], NULL, 10), (int) strtol(row[2], NULL, 10), &pid)) {
					pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to create PID string\n");
					if (pid)
						free(pid);
					pid = NULL;
				}
			}

			if (row[3]) {
				snprintf(source_buffer, OPH_PID_SIZE, "- SOURCE: %s", row[3]);
				snprintf(source_buffer_json, OPH_PID_SIZE, "%s", row[3]);
			} else {
				source_buffer[0] = 0;
				source_buffer_json[0] = 0;
			}

			//If last element of tree
			if (!i) {
				printf(" └─ %s (%s) %s\n", (pid ? pid : "-"), (row[1] ? row[1] : "-"), source_buffer);
			} else {
				printf(" ├─ %s (%s) %s\n", (pid ? pid : "-"), (row[1] ? row[1] : "-"), source_buffer);
			}
			i--;

			if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_CUBEIO)) {
				char *my_row[4] = { (pid2 ? pid2 : ""), (row[1] ? row[1] : ""), (pid ? pid : ""), source_buffer_json };
				if (oph_json_add_grid_row(oper_json, OPH_JSON_OBJKEY_CUBEIO, my_row)) {
					pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRID ROW error\n");
					logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_CUBEIO_MEMORY_ERROR, "output grid row");
					mysql_free_result(io_datacubes);
					if (pid)
						free(pid);
					if (pid2)
						free(pid2);
					return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
				}
			}

			if (oph_json_is_objkey_printable(objkeys, objkeys_num, OPH_JSON_OBJKEY_CUBEIO_GRAPH)) {
				unsigned int nn, nnn;
				int found = 0;
				for (nn = 0; nn < oper_json->response_num; nn++) {
					if (!strcmp(oper_json->response[nn].objkey, OPH_JSON_OBJKEY_CUBEIO_GRAPH)) {
						for (nnn = 0; nnn < ((oph_json_obj_graph *) (oper_json->response[nn].objcontent))[0].nodevalues_num1; nnn++) {
							if (!strcmp((pid ? pid : ""), ((oph_json_obj_graph *) (oper_json->response[nn].objcontent))[0].nodevalues[nnn][0])) {
								found = 1;
								break;
							}
						}
						break;
					}
				}
				char *my_row[2] = { (pid ? pid : ""), source_buffer_json };
				if (!found) {
					if (oph_json_add_graph_node(oper_json, OPH_JSON_OBJKEY_CUBEIO_GRAPH, my_row)) {
						pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRAPH NODE error\n");
						logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_CUBEIO_MEMORY_ERROR, "output graph node");
						mysql_free_result(io_datacubes);
						if (pid)
							free(pid);
						if (pid2)
							free(pid2);
						return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
					}
				}
				int node1 = -1, node2 = -1;
				for (nn = 0; nn < oper_json->response_num; nn++) {
					if (!strcmp(oper_json->response[nn].objkey, OPH_JSON_OBJKEY_CUBEIO_GRAPH)) {
						for (nnn = 0; nnn < ((oph_json_obj_graph *) (oper_json->response[nn].objcontent))[0].nodevalues_num1; nnn++) {
							if (node1 != -1 && node2 != -1)
								break;
							if (!strcmp((pid2 ? pid2 : ""), ((oph_json_obj_graph *) (oper_json->response[nn].objcontent))[0].nodevalues[nnn][0]))
								node1 = nnn;
							else if (!strcmp((pid ? pid : ""), ((oph_json_obj_graph *) (oper_json->response[nn].objcontent))[0].nodevalues[nnn][0]))
								node2 = nnn;
						}
						break;
					}
				}

				int node_link = 0;
				found = 0;
				for (nn = 0; nn < oper_json->response_num; nn++) {
					if (!strcmp(oper_json->response[nn].objkey, OPH_JSON_OBJKEY_CUBEIO_GRAPH)) {
						for (nnn = 0; nnn < ((oph_json_obj_graph *) oper_json->response[nn].objcontent)[0].nodelinks[node1].links_num; nnn++) {
							node_link = (int) strtol(((oph_json_obj_graph *) oper_json->response[nn].objcontent)[0].nodelinks[node1].links[nnn].node, NULL, 10);
							if (node_link == node2) {
								found = 1;
								break;
							}
						}
						if (found == 1)
							break;
					}
				}
				if (!found) {
					if (oph_json_add_graph_link(oper_json, OPH_JSON_OBJKEY_CUBEIO_GRAPH, node1, node2, (const char *) (row[1] ? row[1] : ""))) {
						pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRAPH LINK error\n");
						logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_CUBEIO_MEMORY_ERROR, "output graph link");
						mysql_free_result(io_datacubes);
						if (pid)
							free(pid);
						if (pid2)
							free(pid2);
						return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
					}
				}
			}

			if (_oph_cubeio_print_children(uri, oDB, level, (int) strtol(row[2], NULL, 10), child_type, id_container_in, oper_json, objkeys, objkeys_num))
				break;

			if (pid)
				free(pid);
			pid = NULL;

		}
		if (pid2)
			free(pid2);
		pid2 = NULL;
	}
	mysql_free_result(io_datacubes);
	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_METADATA_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;

  MYSQL_RES *read_result = NULL;
  MYSQL_FIELD *fields;
  MYSQL_ROW row;
  int num_fields;
  int num_rows;
  int i,j,len;

  //execute requested crud operation
  if(oph_metadata_crud(((OPH_METADATA_operator_handle*)handle->operator_handle),&read_result)){
	pmesg(LOG_ERROR, __FILE__, __LINE__, "Unable to manage metadata\n");
	logging(LOG_ERROR,__FILE__,__LINE__, OPH_GENERIC_CONTAINER_ID,OPH_LOG_OPH_METADATA_CRUD_ERROR);
	return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
  }

  if (((OPH_METADATA_operator_handle*)handle->operator_handle)->mode==OPH_METADATA_MODE_READ_VALUE)
  {
	num_rows = mysql_num_rows(read_result);
	char message[OPH_COMMON_BUFFER_LEN];
	snprintf(message,OPH_COMMON_BUFFER_LEN,"Found %d items",num_rows);
	printf("%s\n",message);
	if (oph_json_is_objkey_printable(((OPH_METADATA_operator_handle*)handle->operator_handle)->objkeys,((OPH_METADATA_operator_handle*)handle->operator_handle)->objkeys_num,OPH_JSON_OBJKEY_METADATA_SUMMARY))
	{
		if (oph_json_add_text(handle->operator_json,OPH_JSON_OBJKEY_METADATA_SUMMARY,"Summary",message))
		{
			pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD TEXT error\n");
			logging(LOG_WARNING,__FILE__,__LINE__, OPH_GENERIC_CONTAINER_ID,"ADD TEXT error\n");
			return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
		}
	}

      //Empty set
      if(!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_METADATA_NO_ROWS_FOUND);
        mysql_free_result(read_result);
        return OPH_ANALYTICS_OPERATOR_SUCCESS;
      }

      fields = mysql_fetch_fields(read_result);
      num_fields = mysql_num_fields(read_result);

      printf("+");
      for (i = 0; i < num_fields; i++) {
          printf("-");
          len = (fields[i].max_length > fields[i].name_length)?fields[i].max_length:fields[i].name_length;
          for (j = 0; j < len; j++) {
              printf("-");
          }
          printf("-+");
      }
      printf("\n");

      printf("|");
      for (i = 0; i < num_fields; i++) {
          printf(" ");
          len = (fields[i].max_length > fields[i].name_length)?fields[i].max_length:fields[i].name_length;
          printf("%-*s",len,fields[i].name);
          printf(" |");
      }
      printf("\n");

	int objkey_printable = oph_json_is_objkey_printable(((OPH_METADATA_operator_handle*)handle->operator_handle)->objkeys,((OPH_METADATA_operator_handle*)handle->operator_handle)->objkeys_num,OPH_JSON_OBJKEY_METADATA_LIST), iii, jjj;
	if (objkey_printable)
	{
		char **jsonkeys = NULL;
		char **fieldtypes = NULL;
		jsonkeys = (char **)malloc(sizeof(char *)*num_fields);
		if (!jsonkeys) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
			logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_METADATA_MEMORY_ERROR_INPUT, "keys" );
			mysql_free_result(read_result);
			return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
		}
		for (jjj=0;jjj<num_fields;++jjj)
		{
			jsonkeys[jjj] = strdup(fields[jjj].name ? fields[jjj].name : "");
			if (!jsonkeys[jjj]) {
				pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
				logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_METADATA_MEMORY_ERROR_INPUT, "key" );
				for (iii=0;iii<jjj;iii++) if (jsonkeys[iii]) free(jsonkeys[iii]);
				if (jsonkeys) free(jsonkeys);
				mysql_free_result(read_result);
				return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
			}
		}
		fieldtypes = (char **)malloc(sizeof(char *)*num_fields);
		if (!fieldtypes) {
			pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
			logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_METADATA_MEMORY_ERROR_INPUT, "fieldtypes" );
			for (iii = 0; iii < num_fields; iii++) if (jsonkeys[iii]) free(jsonkeys[iii]);
			if (jsonkeys) free(jsonkeys);
			mysql_free_result(read_result);
			return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
		}
		for (jjj=0;jjj<num_fields;++jjj)
		{
			fieldtypes[jjj] = strdup(OPH_JSON_STRING);
			if (!fieldtypes[jjj]) {
				pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
				logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_METADATA_MEMORY_ERROR_INPUT, "fieldtype" );
				for (iii = 0; iii < num_fields; iii++) if (jsonkeys[iii]) free(jsonkeys[iii]);
				if (jsonkeys) free(jsonkeys);
				for (iii = 0; iii < jjj; iii++) if (fieldtypes[iii]) free(fieldtypes[iii]);
				if (fieldtypes) free(fieldtypes);
				mysql_free_result(read_result);
				return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
			}
		}
		if (oph_json_add_grid(handle->operator_json,OPH_JSON_OBJKEY_METADATA_LIST,"Searching results",NULL,jsonkeys,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");
			for (iii = 0; iii < num_fields; iii++) if (jsonkeys[iii]) free(jsonkeys[iii]);
			if (jsonkeys) free(jsonkeys);
			for (iii = 0; iii < num_fields; iii++) if (fieldtypes[iii]) free(fieldtypes[iii]);
			if (fieldtypes) free(fieldtypes);
			mysql_free_result(read_result);
			return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
		}
		for (iii = 0; iii < num_fields; iii++) if (jsonkeys[iii]) free(jsonkeys[iii]);
		if (jsonkeys) free(jsonkeys);
		for (iii = 0; iii < num_fields; iii++) if (fieldtypes[iii]) free(fieldtypes[iii]);
		if (fieldtypes) free(fieldtypes);
	}

      printf("+");
      for (i = 0; i < num_fields; i++) {
          printf("-");
          len = (fields[i].max_length > fields[i].name_length)?fields[i].max_length:fields[i].name_length;
          for (j = 0; j < len; j++) {
              printf("-");
          }
          printf("-+");
      }
      printf("\n");

      //For each ROW
      while((row = mysql_fetch_row(read_result))){
          printf("|");
          for (i = 0; i < num_fields; i++) {
              printf(" ");
              len = (fields[i].max_length > fields[i].name_length)?fields[i].max_length:fields[i].name_length;
              printf("%-*s",len,row[i]?row[i]:"");
              printf(" |");
          }
          printf("\n");

		if (objkey_printable)
		{
			  char **jsonvalues = NULL;
			  jsonvalues = (char **)calloc(num_fields,sizeof(char *));
			  if (!jsonvalues) {
				  pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
				  logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_METADATA_MEMORY_ERROR_INPUT, "values" );
				  mysql_free_result(read_result);
				  return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
			  }
			  for (jjj=0;jjj<num_fields;++jjj)
			  {
				  jsonvalues[jjj] = strdup(row[jjj] ? row[jjj] : "");
				  if (!jsonvalues[jjj]) {
					  pmesg(LOG_ERROR, __FILE__, __LINE__, "Error allocating memory\n");
					  logging(LOG_ERROR, __FILE__, __LINE__, OPH_GENERIC_CONTAINER_ID, OPH_LOG_OPH_METADATA_MEMORY_ERROR_INPUT, "value" );
					  for (iii = 0; iii < jjj; iii++) if (jsonvalues[iii]) free(jsonvalues[iii]);
					  if (jsonvalues) free(jsonvalues);
					  mysql_free_result(read_result);
					  return OPH_ANALYTICS_OPERATOR_MEMORY_ERR;
				  }
			  }
			  if (oph_json_add_grid_row(handle->operator_json,OPH_JSON_OBJKEY_METADATA_LIST,jsonvalues))
			  {
				  pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD GRID ROW error\n");
				  logging(LOG_WARNING,__FILE__,__LINE__, OPH_GENERIC_CONTAINER_ID,"ADD GRID ROW error\n");
				  for (iii = 0; iii < num_fields; iii++) if (jsonvalues[iii]) free(jsonvalues[iii]);
				  if (jsonvalues) free(jsonvalues);
				  mysql_free_result(read_result);
				  return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
			  }
			  for (iii = 0; iii < num_fields; iii++) if (jsonvalues[iii]) free(jsonvalues[iii]);
			  if (jsonvalues) free(jsonvalues);
		}
      }

      printf("+");
      for (i = 0; i < num_fields; i++) {
          printf("-");
          len = (fields[i].max_length > fields[i].name_length)?fields[i].max_length:fields[i].name_length;
          for (j = 0; j < len; j++) {
              printf("-");
          }
          printf("-+");
      }
      printf("\n");

      mysql_free_result(read_result);
  } else {
	char message[OPH_COMMON_BUFFER_LEN];
	snprintf(message,OPH_COMMON_BUFFER_LEN,"Operation successfully completed!");
	printf("%s\n",message);
	if (oph_json_is_objkey_printable(((OPH_METADATA_operator_handle*)handle->operator_handle)->objkeys,((OPH_METADATA_operator_handle*)handle->operator_handle)->objkeys_num,OPH_JSON_OBJKEY_METADATA_SUMMARY))
	{
		if (oph_json_add_text(handle->operator_json,OPH_JSON_OBJKEY_METADATA_SUMMARY,"Summary",message))
		{
			pmesg(LOG_ERROR, __FILE__, __LINE__, "ADD TEXT error\n");
			logging(LOG_WARNING,__FILE__,__LINE__, OPH_GENERIC_CONTAINER_ID,"ADD TEXT error\n");
			return OPH_ANALYTICS_OPERATOR_UTILITY_ERROR;
		}
	}
  }

  return OPH_ANALYTICS_OPERATOR_SUCCESS;
}