text:
#include <rte_flow.h>
#include <rte_flow_driver.h>
#include <rte_malloc.h>
#include <rte_log.h>

#include <arpa/inet.h>

#include "mrvl_flow.h"
#include "mrvl_qos.h"

/** Number of rules in the classifier table. */
#define MRVL_CLS_MAX_NUM_RULES 20

/** Size of the classifier key and mask strings. */
#define MRVL_CLS_STR_SIZE_MAX 40

#define MRVL_VLAN_ID_MASK 0x0fff
#define MRVL_VLAN_PRI_MASK 0x7000
#define MRVL_IPV4_DSCP_MASK 0xfc
#define MRVL_IPV4_ADDR_MASK 0xffffffff
#define MRVL_IPV6_FLOW_MASK 0x0fffff

/**
 * Allocate memory for classifier rule key and mask fields.
 *
 * @param field Pointer to the classifier rule.
 * @returns 0 in case of success, negative value otherwise.
 */
static int
mrvl_alloc_key_mask(struct pp2_cls_rule_key_field *field)
{
	unsigned int id = rte_socket_id();

	field->key = rte_zmalloc_socket(NULL, MRVL_CLS_STR_SIZE_MAX, 0, id);
	if (!field->key)
		goto out;

	field->mask = rte_zmalloc_socket(NULL, MRVL_CLS_STR_SIZE_MAX, 0, id);
	if (!field->mask)
		goto out_mask;

	return 0;
out_mask:
	rte_free(field->key);
out:
	field->key = NULL;
	field->mask = NULL;
	return -1;
}

/**
 * Free memory allocated for classifier rule key and mask fields.
 *
 * @param field Pointer to the classifier rule.
 */
static void
mrvl_free_key_mask(struct pp2_cls_rule_key_field *field)
{
	rte_free(field->key);
	rte_free(field->mask);
	field->key = NULL;
	field->mask = NULL;
}

/**
 * Free memory allocated for all classifier rule key and mask fields.
 *
 * @param rule Pointer to the classifier table rule.
 */
static void
mrvl_free_all_key_mask(struct pp2_cls_tbl_rule *rule)
{
	int i;

	for (i = 0; i < rule->num_fields; i++)
		mrvl_free_key_mask(&rule->fields[i]);
	rule->num_fields = 0;
}

/*
 * Initialize rte flow item parsing.
 *
 * @param item Pointer to the flow item.
 * @param spec_ptr Pointer to the specific item pointer.
 * @param mask_ptr Pointer to the specific item's mask pointer.
 * @def_mask Pointer to the default mask.
 * @size Size of the flow item.
 * @error Pointer to the rte flow error.
 * @returns 0 in case of success, negative value otherwise.
 */
static int
mrvl_parse_init(const struct rte_flow_item *item,
		const void **spec_ptr,
		const void **mask_ptr,
		const void *def_mask,
		unsigned int size,
		struct rte_flow_error *error)
{
	const uint8_t *spec;
	const uint8_t *mask;
	const uint8_t *last;
	uint8_t zeros[size];

	memset(zeros, 0, size);

	if (item == NULL) {
		rte_flow_error_set(error, EINVAL,
				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
				   "NULL item\n");
		return -rte_errno;
	}

	if ((item->last != NULL || item->mask != NULL) && item->spec == NULL) {
		rte_flow_error_set(error, EINVAL,
				   RTE_FLOW_ERROR_TYPE_ITEM, item,
				   "Mask or last is set without spec\n");
		return -rte_errno;
	}

	/*
	 * If "mask" is not set, default mask is used,
	 * but if default mask is NULL, "mask" should be set.
	 */
	if (item->mask == NULL) {
		if (def_mask == NULL) {
			rte_flow_error_set(error, EINVAL,
					   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
					   "Mask should be specified\n");
			return -rte_errno;
		}

		mask = (const uint8_t *)def_mask;
	} else {
		mask = (const uint8_t *)item->mask;
	}

	spec = (const uint8_t *)item->spec;
	last = (const uint8_t *)item->last;

	if (spec == NULL) {
		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
				   NULL, "Spec should be specified\n");
		return -rte_errno;
	}

	/*
	 * If field values in "last" are either 0 or equal to the corresponding
	 * values in "spec" then they are ignored.
	 */
	if (last != NULL &&
	    !memcmp(last, zeros, size) &&
	    memcmp(last, spec, size) != 0) {
		rte_flow_error_set(error, ENOTSUP,
				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
				   "Ranging is not supported\n");
		return -rte_errno;
	}

	*spec_ptr = spec;
	*mask_ptr = mask;

	return 0;
}

/**
 * Parse the eth flow item.
 *
 * This will create classifier rule that matches either destination or source
 * mac.
 *
 * @param spec Pointer to the specific flow item.
 * @param mask Pointer to the specific flow item's mask.
 * @param parse_dst Parse either destination or source mac address.
 * @param flow Pointer to the flow.
 * @return 0 in case of success, negative error value otherwise.
 */
static int
mrvl_parse_mac(const struct rte_flow_item_eth *spec,
	       const struct rte_flow_item_eth *mask,
	       int parse_dst, struct rte_flow *flow)
{
	struct pp2_cls_rule_key_field *key_field;
	const uint8_t *k, *m;

	if (parse_dst) {
		k = spec->dst.addr_bytes;
		m = mask->dst.addr_bytes;

		flow->table_key.proto_field[flow->rule.num_fields].field.eth =
			MV_NET_ETH_F_DA;
	} else {
		k = spec->src.addr_bytes;
		m = mask->src.addr_bytes;

		flow->table_key.proto_field[flow->rule.num_fields].field.eth =
			MV_NET_ETH_F_SA;
	}

	key_field = &flow->rule.fields[flow->rule.num_fields];
	mrvl_alloc_key_mask(key_field);
	key_field->size = 6;

	snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX,
		 RTE_ETHER_ADDR_PRT_FMT,
		 k[0], k[1], k[2], k[3], k[4], k[5]);

	snprintf((char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX,
		 RTE_ETHER_ADDR_PRT_FMT,
		 m[0], m[1], m[2], m[3], m[4], m[5]);

	flow->table_key.proto_field[flow->rule.num_fields].proto =
		MV_NET_PROTO_ETH;
	flow->table_key.key_size += key_field->size;

	flow->rule.num_fields += 1;

	return 0;
}

/**
 * Helper for parsing the eth flow item destination mac address.
 *
 * @param spec Pointer to the specific flow item.
 * @param mask Pointer to the specific flow item's mask.
 * @param flow Pointer to the flow.
 * @return 0 in case of success, negative error value otherwise.
 */
static inline int
mrvl_parse_dmac(const struct rte_flow_item_eth *spec,
		const struct rte_flow_item_eth *mask,
		struct rte_flow *flow)
{
	return mrvl_parse_mac(spec, mask, 1, flow);
}

/**
 * Helper for parsing the eth flow item source mac address.
 *
 * @param spec Pointer to the specific flow item.
 * @param mask Pointer to the specific flow item's mask.
 * @param flow Pointer to the flow.
 * @return 0 in case of success, negative error value otherwise.
 */
static inline int
mrvl_parse_smac(const struct rte_flow_item_eth *spec,
		const struct rte_flow_item_eth *mask,
		struct rte_flow *flow)
{
	return mrvl_parse_mac(spec, mask, 0, flow);
}

/**
 * Parse the ether type field of the eth flow item.
 *
 * @param spec Pointer to the specific flow item.
 * @param mask Pointer to the specific flow item's mask.
 * @param flow Pointer to the flow.
 * @return 0 in case of success, negative error value otherwise.
 */
static int
mrvl_parse_type(const struct rte_flow_item_eth *spec,
		const struct rte_flow_item_eth *mask __rte_unused,
		struct rte_flow *flow)
{
	struct pp2_cls_rule_key_field *key_field;
	uint16_t k;

	key_field = &flow->rule.fields[flow->rule.num_fields];
	mrvl_alloc_key_mask(key_field);
	key_field->size = 2;

	k = rte_be_to_cpu_16(spec->type);
	snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);

	flow->table_key.proto_field[flow->rule.num_fields].proto =
		MV_NET_PROTO_ETH;
	flow->table_key.proto_field[flow->rule.num_fields].field.eth =
		MV_NET_ETH_F_TYPE;
	flow->table_key.key_size += key_field->size;

	flow->rule.num_fields += 1;

	return 0;
}

/**
 * Parse the vid field of the vlan rte flow item.
 *
 * This will create classifier rule that matches vid.
 *
 * @param spec Pointer to the specific flow item.
 * @param mask Pointer to the specific flow item's mask.
 * @param flow Pointer to the flow.
 * @return 0 in case of success, negative error value otherwise.
 */
static int
mrvl_parse_vlan_id(const struct rte_flow_item_vlan *spec,
		   const struct rte_flow_item_vlan *mask __rte_unused,
		   struct rte_flow *flow)
{
	struct pp2_cls_rule_key_field *key_field;
	uint16_t k;

	key_field = &flow->rule.fields[flow->rule.num_fields];
	mrvl_alloc_key_mask(key_field);
	key_field->size = 2;

	k = rte_be_to_cpu_16(spec->tci) & MRVL_VLAN_ID_MASK;
	snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);

	flow->table_key.proto_field[flow->rule.num_fields].proto =
		MV_NET_PROTO_VLAN;
	flow->table_key.proto_field[flow->rule.num_fields].field.vlan =
		MV_NET_VLAN_F_ID;
	flow->table_key.key_size += key_field->size;

	flow->rule.num_fields += 1;

	return 0;
}

/**
 * Parse the pri field of the vlan rte flow item.
 *
 * This will create classifier rule that matches pri.
 *
 * @param spec Pointer to the specific flow item.
 * @param mask Pointer to the specific flow item's mask.
 * @param flow Pointer to the flow.
 * @return 0 in case of success, negative error value otherwise.
 */
static int
mrvl_parse_vlan_pri(const struct rte_flow_item_vlan *spec,
		    const struct rte_flow_item_vlan *mask __rte_unused,
		    struct rte_flow *flow)
{
	struct pp2_cls_rule_key_field *key_field;
	uint16_t k;

	key_field = &flow->rule.fields[flow->rule.num_fields];
	mrvl_alloc_key_mask(key_field);
	key_field->size = 1;

	k = (rte_be_to_cpu_16(spec->tci) & MRVL_VLAN_PRI_MASK) >> 13;
	snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);

	flow->table_key.proto_field[flow->rule.num_fields].proto =
		MV_NET_PROTO_VLAN;
	flow->table_key.proto_field[flow->rule.num_fields].field.vlan =
		MV_NET_VLAN_F_PRI;
	flow->table_key.key_size += key_field->size;

	flow->rule.num_fields += 1;

	return 0;
}

/**
 * Parse the dscp field of the ipv4 rte flow item.
 *
 * This will create classifier rule that matches dscp field.
 *
 * @param spec Pointer to the specific flow item.
 * @param mask Pointer to the specific flow item's mask.
 * @param flow Pointer to the flow.
 * @return 0 in case of success, negative error value otherwise.
 */
static int
mrvl_parse_ip4_dscp(const struct rte_flow_item_ipv4 *spec,
		    const struct rte_flow_item_ipv4 *mask,
		    struct rte_flow *flow)
{
	struct pp2_cls_rule_key_field *key_field;
	uint8_t k, m;

	key_field = &flow->rule.fields[flow->rule.num_fields];
	mrvl_alloc_key_mask(key_field);
	key_field->size = 1;

	k = (spec->hdr.type_of_service & MRVL_IPV4_DSCP_MASK) >> 2;
	m = (mask->hdr.type_of_service & MRVL_IPV4_DSCP_MASK) >> 2;
	snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
	snprintf((char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX, "%u", m);

	flow->table_key.proto_field[flow->rule.num_fields].proto =
		MV_NET_PROTO_IP4;
	flow->table_key.proto_field[flow->rule.num_fields].field.ipv4 =
		MV_NET_IP4_F_DSCP;
	flow->table_key.key_size += key_field->size;

	flow->rule.num_fields += 1;

	return 0;
}

/**
 * Parse either source or destination ip addresses of the ipv4 flow item.
 *
 * This will create classifier rule that matches either destination
 * or source ip field.
 *
 * @param spec Pointer to the specific flow item.
 * @param mask Pointer to the specific flow item's mask.
 * @param parse_dst Parse either destination or source ip address.
 * @param flow Pointer to the flow.
 * @return 0 in case of success, negative error value otherwise.
 */
static int
mrvl_parse_ip4_addr(const struct rte_flow_item_ipv4 *spec,
		    const struct rte_flow_item_ipv4 *mask,
		    int parse_dst, struct rte_flow *flow)
{
	struct pp2_cls_rule_key_field *key_field;
	struct in_addr k;
	uint32_t m;

	memset(&k, 0, sizeof(k));
	if (parse_dst) {
		k.s_addr = spec->hdr.dst_addr;
		m = rte_be_to_cpu_32(mask->hdr.dst_addr);

		flow->table_key.proto_field[flow->rule.num_fields].field.ipv4 =
			MV_NET_IP4_F_DA;
	} else {
		k.s_addr = spec->hdr.src_addr;
		m = rte_be_to_cpu_32(mask->hdr.src_addr);

		flow->table_key.proto_field[flow->rule.num_fields].field.ipv4 =
			MV_NET_IP4_F_SA;
	}

	key_field = &flow->rule.fields[flow->rule.num_fields];
	mrvl_alloc_key_mask(key_field);
	key_field->size = 4;

	inet_ntop(AF_INET, &k, (char *)key_field->key, MRVL_CLS_STR_SIZE_MAX);
	snprintf((char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX, "0x%x", m);

	flow->table_key.proto_field[flow->rule.num_fields].proto =
		MV_NET_PROTO_IP4;
	flow->table_key.key_size += key_field->size;

	flow->rule.num_fields += 1;

	return 0;
}

/**
 * Helper for parsing destination ip of the ipv4 flow item.
 *
 * @param spec Pointer to the specific flow item.
 * @param mask Pointer to the specific flow item's mask.
 * @param flow Pointer to the flow.
 * @return 0 in case of success, negative error value otherwise.
 */
static inline int
mrvl_parse_ip4_dip(const struct rte_flow_item_ipv4 *spec,
		   const struct rte_flow_item_ipv4 *mask,
		   struct rte_flow *flow)
{
	return mrvl_parse_ip4_addr(spec, mask, 1, flow);
}

/**
 * Helper for parsing source ip of the ipv4 flow item.
 *
 * @param spec Pointer to the specific flow item.
 * @param mask Pointer to the specific flow item's mask.
 * @param flow Pointer to the flow.
 * @return 0 in case of success, negative error value otherwise.
 */
static inline int
mrvl_parse_ip4_sip(const struct rte_flow_item_ipv4 *spec,
		   const struct rte_flow_item_ipv4 *mask,
		   struct rte_flow *flow)
{
	return mrvl_parse_ip4_addr(spec, mask, 0, flow);
}

/**
 * Parse the proto field of the ipv4 rte flow item.
 *
 * This will create classifier rule that matches proto field.
 *
 * @param spec Pointer to the specific flow item.
 * @param mask Pointer to the specific flow item's mask.
 * @param flow Pointer to the flow.
 * @return 0 in case of success, negative error value otherwise.
 */
static int
mrvl_parse_ip4_proto(const struct rte_flow_item_ipv4 *spec,
		     const struct rte_flow_item_ipv4 *mask __rte_unused,
		     struct rte_flow *flow)
{
	struct pp2_cls_rule_key_field *key_field;
	uint8_t k = spec->hdr.next_proto_id;

	key_field = &flow->rule.fields[flow->rule.num_fields];
	mrvl_alloc_key_mask(key_field);
	key_field->size = 1;

	snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);

	flow->table_key.proto_field[flow->rule.num_fields].proto =
		MV_NET_PROTO_IP4;
	flow->table_key.proto_field[flow->rule.num_fields].field.ipv4 =
		MV_NET_IP4_F_PROTO;
	flow->table_key.key_size += key_field->size;

	flow->rule.num_fields += 1;

	return 0;
}

/**
 * Parse either source or destination ip addresses of the ipv6 rte flow item.
 *
 * This will create classifier rule that matches either destination
 * or source ip field.
 *
 * @param spec Pointer to the specific flow item.
 * @param mask Pointer to the specific flow item's mask.
 * @param parse_dst Parse either destination or source ipv6 address.
 * @param flow Pointer to the flow.
 * @return 0 in case of success, negative error value otherwise.
 */
static int
mrvl_parse_ip6_addr(const struct rte_flow_item_ipv6 *spec,
	       const struct rte_flow_item_ipv6 *mask,
	       int parse_dst, struct rte_flow *flow)
{
	struct pp2_cls_rule_key_field *key_field;
	int size = sizeof(spec->hdr.dst_addr);
	struct in6_addr k, m;

	memset(&k, 0, sizeof(k));
	if (parse_dst) {
		memcpy(k.s6_addr, spec->hdr.dst_addr, size);
		memcpy(m.s6_addr, mask->hdr.dst_addr, size);

		flow->table_key.proto_field[flow->rule.num_fields].field.ipv6 =
			MV_NET_IP6_F_DA;
	} else {
		memcpy(k.s6_addr, spec->hdr.src_addr, size);
		memcpy(m.s6_addr, mask->hdr.src_addr, size);

		flow->table_key.proto_field[flow->rule.num_fields].field.ipv6 =
			MV_NET_IP6_F_SA;
	}

	key_field = &flow->rule.fields[flow->rule.num_fields];
	mrvl_alloc_key_mask(key_field);
	key_field->size = 16;

	inet_ntop(AF_INET6, &k, (char *)key_field->key, MRVL_CLS_STR_SIZE_MAX);
	inet_ntop(AF_INET6, &m, (char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX);

	flow->table_key.proto_field[flow->rule.num_fields].proto =
		MV_NET_PROTO_IP6;
	flow->table_key.key_size += key_field->size;

	flow->rule.num_fields += 1;

	return 0;
}

/**
 * Helper for parsing destination ip of the ipv6 flow item.
 *
 * @param spec Pointer to the specific flow item.
 * @param mask Pointer to the specific flow item's mask.
 * @param flow Pointer to the flow.
 * @return 0 in case of success, negative error value otherwise.
 */
static inline int
mrvl_parse_ip6_dip(const struct rte_flow_item_ipv6 *spec,
		   const struct rte_flow_item_ipv6 *mask,
		   struct rte_flow *flow)
{
	return mrvl_parse_ip6_addr(spec, mask, 1, flow);
}

/**
 * Helper for parsing source ip of the ipv6 flow item.
 *
 * @param spec Pointer to the specific flow item.
 * @param mask Pointer to the specific flow item's mask.
 * @param flow Pointer to the flow.
 * @return 0 in case of success, negative error value otherwise.
 */
static inline int
mrvl_parse_ip6_sip(const struct rte_flow_item_ipv6 *spec,
		   const struct rte_flow_item_ipv6 *mask,
		   struct rte_flow *flow)
{
	return mrvl_parse_ip6_addr(spec, mask, 0, flow);
}

/**
 * Parse the flow label of the ipv6 flow item.
 *
 * This will create classifier rule that matches flow field.
 *
 * @param spec Pointer to the specific flow item.
 * @param mask Pointer to the specific flow item's mask.
 * @param flow Pointer to the flow.
 * @return 0 in case of success, negative error value otherwise.
 */
static int
mrvl_parse_ip6_flow(const struct rte_flow_item_ipv6 *spec,
		    const struct rte_flow_item_ipv6 *mask,
		    struct rte_flow *flow)
{
	struct pp2_cls_rule_key_field *key_field;
	uint32_t k = rte_be_to_cpu_32(spec->hdr.vtc_flow) & MRVL_IPV6_FLOW_MASK,
		 m = rte_be_to_cpu_32(mask->hdr.vtc_flow) & MRVL_IPV6_FLOW_MASK;

	key_field = &flow->rule.fields[flow->rule.num_fields];
	mrvl_alloc_key_mask(key_field);
	key_field->size = 3;

	snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
	snprintf((char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX, "%u", m);

	flow->table_key.proto_field[flow->rule.num_fields].proto =
		MV_NET_PROTO_IP6;
	flow->table_key.proto_field[flow->rule.num_fields].field.ipv6 =
		MV_NET_IP6_F_FLOW;
	flow->table_key.key_size += key_field->size;

	flow->rule.num_fields += 1;

	return 0;
}

/**
 * Parse the next header of the ipv6 flow item.
 *
 * This will create classifier rule that matches next header field.
 *
 * @param spec Pointer to the specific flow item.
 * @param mask Pointer to the specific flow item's mask.
 * @param flow Pointer to the flow.
 * @return 0 in case of success, negative error value otherwise.
 */
static int
mrvl_parse_ip6_next_hdr(const struct rte_flow_item_ipv6 *spec,
			const struct rte_flow_item_ipv6 *mask __rte_unused,
			struct rte_flow *flow)
{
	struct pp2_cls_rule_key_field *key_field;
	uint8_t k = spec->hdr.proto;

	key_field = &flow->rule.fields[flow->rule.num_fields];
	mrvl_alloc_key_mask(key_field);
	key_field->size = 1;

	snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);

	flow->table_key.proto_field[flow->rule.num_fields].proto =
		MV_NET_PROTO_IP6;
	flow->table_key.proto_field[flow->rule.num_fields].field.ipv6 =
		MV_NET_IP6_F_NEXT_HDR;
	flow->table_key.key_size += key_field->size;

	flow->rule.num_fields += 1;

	return 0;
}

/**
 * Parse destination or source port of the tcp flow item.
 *
 * This will create classifier rule that matches either destination or
 * source tcp port.
 *
 * @param spec Pointer to the specific flow item.
 * @param mask Pointer to the specific flow item's mask.
 * @param parse_dst Parse either destination or source port.
 * @param flow Pointer to the flow.
 * @return 0 in case of success, negative error value otherwise.
 */
static int
mrvl_parse_tcp_port(const struct rte_flow_item_tcp *spec,
		    const struct rte_flow_item_tcp *mask __rte_unused,
		    int parse_dst, struct rte_flow *flow)
{
	struct pp2_cls_rule_key_field *key_field;
	uint16_t k;

	key_field = &flow->rule.fields[flow->rule.num_fields];
	mrvl_alloc_key_mask(key_field);
	key_field->size = 2;

	if (parse_dst) {
		k = rte_be_to_cpu_16(spec->hdr.dst_port);

		flow->table_key.proto_field[flow->rule.num_fields].field.tcp =
			MV_NET_TCP_F_DP;
	} else {
		k = rte_be_to_cpu_16(spec->hdr.src_port);

		flow->table_key.proto_field[flow->rule.num_fields].field.tcp =
			MV_NET_TCP_F_SP;
	}

	snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);

	flow->table_key.proto_field[flow->rule.num_fields].proto =
		MV_NET_PROTO_TCP;
	flow->table_key.key_size += key_field->size;

	flow->rule.num_fields += 1;

	return 0;
}

/**
 * Helper for parsing the tcp source port of the tcp flow item.
 *
 * @param spec Pointer to the specific flow item.
 * @param mask Pointer to the specific flow item's mask.
 * @param flow Pointer to the flow.
 * @return 0 in case of success, negative error value otherwise.
 */
static inline int
mrvl_parse_tcp_sport(const struct rte_flow_item_tcp *spec,
		     const struct rte_flow_item_tcp *mask,
		     struct rte_flow *flow)
{
	return mrvl_parse_tcp_port(spec, mask, 0, flow);
}

/**
 * Helper for parsing the tcp destination port of the tcp flow item.
 *
 * @param spec Pointer to the specific flow item.
 * @param mask Pointer to the specific flow item's mask.
 * @param flow Pointer to the flow.
 * @return 0 in case of success, negative error value otherwise.
 */
static inline int
mrvl_parse_tcp_dport(const struct rte_flow_item_tcp *spec,
		     const struct rte_flow_item_tcp *mask,
		     struct rte_flow *flow)
{
	return mrvl_parse_tcp_port(spec, mask, 1, flow);
}

/**
 * Parse destination or source port of the udp flow item.
 *
 * This will create classifier rule that matches either destination or
 * source udp port.
 *
 * @param spec Pointer to the specific flow item.
 * @param mask Pointer to the specific flow item's mask.
 * @param parse_dst Parse either destination or source port.
 * @param flow Pointer to the flow.
 * @return 0 in case of success, negative error value otherwise.
 */
static int
mrvl_parse_udp_port(const struct rte_flow_item_udp *spec,
		    const struct rte_flow_item_udp *mask __rte_unused,
		    int parse_dst, struct rte_flow *flow)
{
	struct pp2_cls_rule_key_field *key_field;
	uint16_t k;

	key_field = &flow->rule.fields[flow->rule.num_fields];
	mrvl_alloc_key_mask(key_field);
	key_field->size = 2;

	if (parse_dst) {
		k = rte_be_to_cpu_16(spec->hdr.dst_port);

		flow->table_key.proto_field[flow->rule.num_fields].field.udp =
			MV_NET_UDP_F_DP;
	} else {
		k = rte_be_to_cpu_16(spec->hdr.src_port);

		flow->table_key.proto_field[flow->rule.num_fields].field.udp =
			MV_NET_UDP_F_SP;
	}

	snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);

	flow->table_key.proto_field[flow->rule.num_fields].proto =
		MV_NET_PROTO_UDP;
	flow->table_key.key_size += key_field->size;

	flow->rule.num_fields += 1;

	return 0;
}

/**
 * Helper for parsing the udp source port of the udp flow item.
 *
 * @param spec Pointer to the specific flow item.
 * @param mask Pointer to the specific flow item's mask.
 * @param flow Pointer to the flow.
 * @return 0 in case of success, negative error value otherwise.
 */
static inline int
mrvl_parse_udp_sport(const struct rte_flow_item_udp *spec,
		     const struct rte_flow_item_udp *mask,
		     struct rte_flow *flow)
{
	return mrvl_parse_udp_port(spec, mask, 0, flow);
}

/**
 * Helper for parsing the udp destination port of the udp flow item.
 *
 * @param spec Pointer to the specific flow item.
 * @param mask Pointer to the specific flow item's mask.
 * @param flow Pointer to the flow.
 * @return 0 in case of success, negative error value otherwise.
 */
static inline int
mrvl_parse_udp_dport(const struct rte_flow_item_udp *spec,
		     const struct rte_flow_item_udp *mask,
		     struct rte_flow *flow)
{
	return mrvl_parse_udp_port(spec, mask, 1, flow);
}

/**
 * Parse eth flow item.
 *
 * @param item Pointer to the flow item.
 * @param flow Pointer to the flow.
 * @param error Pointer to the flow error.
 * @returns 0 on success, negative value otherwise.
 */
static int
mrvl_parse_eth(const struct rte_flow_item *item, struct rte_flow *flow,
	       struct rte_flow_error *error)
{
	const struct rte_flow_item_eth *spec = NULL, *mask = NULL;
	struct rte_ether_addr zero;
	int ret;

	ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
			      &rte_flow_item_eth_mask,
			      sizeof(struct rte_flow_item_eth), error);
	if (ret)
		return ret;

	memset(&zero, 0, sizeof(zero));

	if (memcmp(&mask->dst, &zero, sizeof(mask->dst))) {
		ret = mrvl_parse_dmac(spec, mask, flow);
		if (ret)
			goto out;
	}

	if (memcmp(&mask->src, &zero, sizeof(mask->src))) {
		ret = mrvl_parse_smac(spec, mask, flow);
		if (ret)
			goto out;
	}

	if (mask->type) {
		MRVL_LOG(WARNING, "eth type mask is ignored");
		ret = mrvl_parse_type(spec, mask, flow);
		if (ret)
			goto out;
	}

	return 0;
out:
	rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
			   "Reached maximum number of fields in cls tbl key\n");
	return -rte_errno;
}

/**
 * Parse vlan flow item.
 *
 * @param item Pointer to the flow item.
 * @param flow Pointer to the flow.
 * @param error Pointer to the flow error.
 * @returns 0 on success, negative value otherwise.
 */
static int
mrvl_parse_vlan(const struct rte_flow_item *item,
		struct rte_flow *flow,
		struct rte_flow_error *error)
{
	const struct rte_flow_item_vlan *spec = NULL, *mask = NULL;
	uint16_t m;
	int ret, i;

	ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
			      &rte_flow_item_vlan_mask,
			      sizeof(struct rte_flow_item_vlan), error);
	if (ret)
		return ret;

	m = rte_be_to_cpu_16(mask->tci);
	if (m & MRVL_VLAN_ID_MASK) {
		MRVL_LOG(WARNING, "vlan id mask is ignored");
		ret = mrvl_parse_vlan_id(spec, mask, flow);
		if (ret)
			goto out;
	}

	if (m & MRVL_VLAN_PRI_MASK) {
		MRVL_LOG(WARNING, "vlan pri mask is ignored");
		ret = mrvl_parse_vlan_pri(spec, mask, flow);
		if (ret)
			goto out;
	}

	if (mask->inner_type) {
		struct rte_flow_item_eth spec_eth = {
			.type = spec->inner_type,
		};
		struct rte_flow_item_eth mask_eth = {
			.type = mask->inner_type,
		};

		/* TPID is not supported so if ETH_TYPE was selected,
		 * error is return. else, classify eth-type with the tpid value
		 */
		for (i = 0; i < flow->rule.num_fields; i++)
			if (flow->table_key.proto_field[i].proto ==
			    MV_NET_PROTO_ETH &&
			    flow->table_key.proto_field[i].field.eth ==
			    MV_NET_ETH_F_TYPE) {
				rte_flow_error_set(error, ENOTSUP,
						   RTE_FLOW_ERROR_TYPE_ITEM,
						   item,
						   "VLAN TPID matching is not supported");
				return -rte_errno;
			}

		MRVL_LOG(WARNING, "inner eth type mask is ignored");
		ret = mrvl_parse_type(&spec_eth, &mask_eth, flow);
		if (ret)
			goto out;
	}

	return 0;
out:
	rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
			   "Reached maximum number of fields in cls tbl key\n");
	return -rte_errno;
}

/**
 * Parse ipv4 flow item.
 *
 * @param item Pointer to the flow item.
 * @param flow Pointer to the flow.
 * @param error Pointer to the flow error.
 * @returns 0 on success, negative value otherwise.
 */
static int
mrvl_parse_ip4(const struct rte_flow_item *item,
	       struct rte_flow *flow,
	       struct rte_flow_error *error)
{
	const struct rte_flow_item_ipv4 *spec = NULL, *mask = NULL;
	int ret;

	ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
			      &rte_flow_item_ipv4_mask,
			      sizeof(struct rte_flow_item_ipv4), error);
	if (ret)
		return ret;

	if (mask->hdr.version_ihl ||
	    mask->hdr.total_length ||
	    mask->hdr.packet_id ||
	    mask->hdr.fragment_offset ||
	    mask->hdr.time_to_live ||
	    mask->hdr.hdr_checksum) {
		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
				   NULL, "Not supported by classifier\n");
		return -rte_errno;
	}

	if (mask->hdr.type_of_service & MRVL_IPV4_DSCP_MASK) {
		ret = mrvl_parse_ip4_dscp(spec, mask, flow);
		if (ret)
			goto out;
	}

	if (mask->hdr.src_addr) {
		ret = mrvl_parse_ip4_sip(spec, mask, flow);
		if (ret)
			goto out;
	}

	if (mask->hdr.dst_addr) {
		ret = mrvl_parse_ip4_dip(spec, mask, flow);
		if (ret)
			goto out;
	}

	if (mask->hdr.next_proto_id) {
		MRVL_LOG(WARNING, "next proto id mask is ignored");
		ret = mrvl_parse_ip4_proto(spec, mask, flow);
		if (ret)
			goto out;
	}

	return 0;
out:
	rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
			   "Reached maximum number of fields in cls tbl key\n");
	return -rte_errno;
}

/**
 * Parse ipv6 flow item.
 *
 * @param item Pointer to the flow item.
 * @param flow Pointer to the flow.
 * @param error Pointer to the flow error.
 * @returns 0 on success, negative value otherwise.
 */
static int
mrvl_parse_ip6(const struct rte_flow_item *item,
	       struct rte_flow *flow,
	       struct rte_flow_error *error)
{
	const struct rte_flow_item_ipv6 *spec = NULL, *mask = NULL;
	struct rte_ipv6_hdr zero;
	uint32_t flow_mask;
	int ret;

	ret = mrvl_parse_init(item, (const void **)&spec,
			      (const void **)&mask,
			      &rte_flow_item_ipv6_mask,
			      sizeof(struct rte_flow_item_ipv6),
			      error);
	if (ret)
		return ret;

	memset(&zero, 0, sizeof(zero));

	if (mask->hdr.payload_len ||
	    mask->hdr.hop_limits) {
		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
				   NULL, "Not supported by classifier\n");
		return -rte_errno;
	}

	if (memcmp(mask->hdr.src_addr,
		   zero.src_addr, sizeof(mask->hdr.src_addr))) {
		ret = mrvl_parse_ip6_sip(spec, mask, flow);
		if (ret)
			goto out;
	}

	if (memcmp(mask->hdr.dst_addr,
		   zero.dst_addr, sizeof(mask->hdr.dst_addr))) {
		ret = mrvl_parse_ip6_dip(spec, mask, flow);
		if (ret)
			goto out;
	}

	flow_mask = rte_be_to_cpu_32(mask->hdr.vtc_flow) & MRVL_IPV6_FLOW_MASK;
	if (flow_mask) {
		ret = mrvl_parse_ip6_flow(spec, mask, flow);
		if (ret)
			goto out;
	}

	if (mask->hdr.proto) {
		MRVL_LOG(WARNING, "next header mask is ignored");
		ret = mrvl_parse_ip6_next_hdr(spec, mask, flow);
		if (ret)
			goto out;
	}

	return 0;
out:
	rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
			   "Reached maximum number of fields in cls tbl key\n");
	return -rte_errno;
}

/**
 * Parse tcp flow item.
 *
 * @param item Pointer to the flow item.
 * @param flow Pointer to the flow.
 * @param error Pointer to the flow error.
 * @returns 0 on success, negative value otherwise.
 */
static int
mrvl_parse_tcp(const struct rte_flow_item *item,
	       struct rte_flow *flow,
	       struct rte_flow_error *error)
{
	const struct rte_flow_item_tcp *spec = NULL, *mask = NULL;
	int ret;

	ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
			      &rte_flow_item_tcp_mask,
			      sizeof(struct rte_flow_item_tcp), error);
	if (ret)
		return ret;

	if (mask->hdr.sent_seq ||
	    mask->hdr.recv_ack ||
	    mask->hdr.data_off ||
	    mask->hdr.tcp_flags ||
	    mask->hdr.rx_win ||
	    mask->hdr.cksum ||
	    mask->hdr.tcp_urp) {
		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
				   NULL, "Not supported by classifier\n");
		return -rte_errno;
	}

	if (mask->hdr.src_port) {
		MRVL_LOG(WARNING, "tcp sport mask is ignored");
		ret = mrvl_parse_tcp_sport(spec, mask, flow);
		if (ret)
			goto out;
	}

	if (mask->hdr.dst_port) {
		MRVL_LOG(WARNING, "tcp dport mask is ignored");
		ret = mrvl_parse_tcp_dport(spec, mask, flow);
		if (ret)
			goto out;
	}

	return 0;
out:
	rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
			   "Reached maximum number of fields in cls tbl key\n");
	return -rte_errno;
}

/**
 * Parse udp flow item.
 *
 * @param item Pointer to the flow item.
 * @param flow Pointer to the flow.
 * @param error Pointer to the flow error.
 * @returns 0 on success, negative value otherwise.
 */
static int
mrvl_parse_udp(const struct rte_flow_item *item,
	       struct rte_flow *flow,
	       struct rte_flow_error *error)
{
	const struct rte_flow_item_udp *spec = NULL, *mask = NULL;
	int ret;

	ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
			      &rte_flow_item_udp_mask,
			      sizeof(struct rte_flow_item_udp), error);
	if (ret)
		return ret;

	if (mask->hdr.dgram_len ||
	    mask->hdr.dgram_cksum) {
		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
				   NULL, "Not supported by classifier\n");
		return -rte_errno;
	}

	if (mask->hdr.src_port) {
		MRVL_LOG(WARNING, "udp sport mask is ignored");
		ret = mrvl_parse_udp_sport(spec, mask, flow);
		if (ret)
			goto out;
	}

	if (mask->hdr.dst_port) {
		MRVL_LOG(WARNING, "udp dport mask is ignored");
		ret = mrvl_parse_udp_dport(spec, mask, flow);
		if (ret)
			goto out;
	}

	return 0;
out:
	rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
			   "Reached maximum number of fields in cls tbl key\n");
	return -rte_errno;
}

static int
mrvl_string_to_hex_values(const uint8_t *input_string,
			  uint8_t *hex_key,
			  uint8_t *length)
{
	char tmp_arr[3], tmp_string[MRVL_CLS_STR_SIZE_MAX], *string_iter;
	int i;

	strcpy(tmp_string, (const char *)input_string);
	string_iter = tmp_string;

	string_iter += 2; /* skip the '0x' */
	*length = ((*length - 2) + 1) / 2;

	for (i = 0; i < *length; i++) {
		strncpy(tmp_arr, string_iter, 2);
		tmp_arr[2] = '\0';
		if (get_val_securely8(tmp_arr, 16,
				      &hex_key[*length - 1 - i]) < 0)
			return -1;
		string_iter += 2;
	}

	return 0;
}

/**
 * Parse raw flow item.
 *
 * @param item Pointer to the flow item.
 * @param flow Pointer to the flow.
 * @param error Pointer to the flow error.
 * @returns 0 on success, negative value otherwise.
 */
static int
mrvl_parse_raw(const struct rte_flow_item *item,
	       struct rte_flow *flow,
	       struct rte_flow_error *error)
{
	const struct rte_flow_item_raw *spec = NULL, *mask = NULL;
	struct pp2_cls_rule_key_field *key_field;
	struct mv_net_udf *udf_params;
	uint8_t length;
	int ret;

	ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
			      &rte_flow_item_raw_mask,
			      sizeof(struct rte_flow_item_raw), error);
	if (ret)
		return ret;

	if (!spec->pattern) {
		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
				   NULL, "pattern pointer MUST be given\n");
		return -rte_errno;
	}

	/* Only hex string is supported; so, it must start with '0x' */
	if (strncmp((const char *)spec->pattern, "0x", 2) != 0)  {
		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
				   NULL, "'pattern' string must start with '0x'\n");
		return -rte_errno;
	}

	if (mask->pattern &&
	    strncmp((const char *)mask->pattern, "0x", 2) != 0)  {
		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
				   NULL, "'mask-pattern' string must start with '0x'\n");
		return -rte_errno;
	}

	if (mask->search && spec->search) {
		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
				   NULL, "'search' option must be '0'\n");
		return -rte_errno;
	}

	if (mask->offset && spec->offset != 0) {
		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
				   NULL, "'offset' option must be '0'\n");
		return -rte_errno;
	}

	if (!mask->relative || !spec->relative) {
		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
				   NULL, "'relative' option must be given and enabled\n");
		return -rte_errno;
	}

	length = spec->length & mask->length;
	if (!length) {
		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
				   NULL, "'length' option must be given bigger than '0'\n");
		return -rte_errno;
	}

	key_field = &flow->rule.fields[flow->rule.num_fields];
	mrvl_alloc_key_mask(key_field);

	/* pattern and length refer to string bytes. we need to convert it to
	 * values.
	 */
	key_field->size = length;
	ret = mrvl_string_to_hex_values(spec->pattern, key_field->key,
					&key_field->size);
	if (ret) {
		rte_flow_error_set(error, EINVAL,
				   RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
				   NULL,
				   "can't convert pattern from string to hex\n");
		return -rte_errno;
	}
	if (mask->pattern) {
		ret = mrvl_string_to_hex_values(mask->pattern, key_field->mask,
						&length);
		if (ret) {
			rte_flow_error_set(error, EINVAL,
					   RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
					   NULL,
					   "can't convert mask-pattern from string to hex\n");
			return -rte_errno;
		}
	} else {
		rte_free(key_field->mask);
		key_field->mask = NULL;
	}

	flow->table_key.proto_field[flow->rule.num_fields].proto =
		MV_NET_UDF;
	udf_params =
		&flow->table_key.proto_field[flow->rule.num_fields].field.udf;
	udf_params->id = flow->next_udf_id++;
	udf_params->size = key_field->size;
	flow->table_key.key_size += key_field->size;

	flow->rule.num_fields += 1;

	return 0;
}

/**
 * Structure used to map specific flow pattern to the pattern parse callback
 * which will iterate over each pattern item and extract relevant data.
 */
static const struct {
	const enum rte_flow_item_type pattern_type;
	int (*parse)(const struct rte_flow_item *pattern,
		struct rte_flow *flow,
		struct rte_flow_error *error);
} mrvl_patterns[] = {
	{ RTE_FLOW_ITEM_TYPE_ETH, mrvl_parse_eth },
	{ RTE_FLOW_ITEM_TYPE_VLAN, mrvl_parse_vlan },
	{ RTE_FLOW_ITEM_TYPE_IPV4, mrvl_parse_ip4 },
	{ RTE_FLOW_ITEM_TYPE_IPV6, mrvl_parse_ip6 },
	{ RTE_FLOW_ITEM_TYPE_TCP, mrvl_parse_tcp },
	{ RTE_FLOW_ITEM_TYPE_UDP, mrvl_parse_udp },
	{ RTE_FLOW_ITEM_TYPE_RAW, mrvl_parse_raw },
	{ RTE_FLOW_ITEM_TYPE_END, NULL }
};

/**
 * Parse flow attribute.
 *
 * This will check whether the provided attribute's flags are supported.
 *
 * @param priv Unused
 * @param attr Pointer to the flow attribute.
 * @param flow Unused
 * @param error Pointer to the flow error.
 * @returns 0 in case of success, negative value otherwise.
 */
static int
mrvl_flow_parse_attr(struct mrvl_priv *priv __rte_unused,
		     const struct rte_flow_attr *attr,
		     struct rte_flow *flow __rte_unused,
		     struct rte_flow_error *error)
{
	if (!attr) {
		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR,
				   NULL, "NULL attribute");
		return -rte_errno;
	}

	if (attr->group) {
		rte_flow_error_set(error, ENOTSUP,
				   RTE_FLOW_ERROR_TYPE_ATTR_GROUP, NULL,
				   "Groups are not supported");
		return -rte_errno;
	}
	if (attr->priority) {
		rte_flow_error_set(error, ENOTSUP,
				   RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, NULL,
				   "Priorities are not supported");
		return -rte_errno;
	}
	if (!attr->ingress) {
		rte_flow_error_set(error, ENOTSUP,
				   RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, NULL,
				   "Only ingress is supported");
		return -rte_errno;
	}
	if (attr->egress) {
		rte_flow_error_set(error, ENOTSUP,
				   RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
				   "Egress is not supported");
		return -rte_errno;
	}
	if (attr->transfer) {
		rte_flow_error_set(error, ENOTSUP,
				   RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, NULL,
				   "Transfer is not supported");
		return -rte_errno;
	}

	return 0;
}

/**
 * Parse flow pattern.
 *
 * Specific classifier rule will be created as well.
 *
 * @param priv Unused
 * @param pattern Pointer to the flow pattern.
 * @param flow Pointer to the flow.
 * @param error Pointer to the flow error.
 * @returns 0 in case of success, negative value otherwise.
 */
static int
mrvl_flow_parse_pattern(struct mrvl_priv *priv __rte_unused,
			const struct rte_flow_item pattern[],
			struct rte_flow *flow,
			struct rte_flow_error *error)
{
	unsigned int i, j;
	int ret;

	for (i = 0; pattern[i].type != RTE_FLOW_ITEM_TYPE_END; i++) {
		if (pattern[i].type == RTE_FLOW_ITEM_TYPE_VOID)
			continue;
		for (j = 0; mrvl_patterns[j].pattern_type !=
			RTE_FLOW_ITEM_TYPE_END; j++) {
			if (mrvl_patterns[j].pattern_type != pattern[i].type)
				continue;

			if (flow->rule.num_fields >=
			    PP2_CLS_TBL_MAX_NUM_FIELDS) {
				rte_flow_error_set(error, ENOSPC,
						   RTE_FLOW_ERROR_TYPE_ITEM_NUM,
						   NULL,
						   "too many pattern (max %d)");
				return -rte_errno;
			}

			ret = mrvl_patterns[j].parse(&pattern[i], flow, error);
			if (ret) {
				mrvl_free_all_key_mask(&flow->rule);
				return ret;
			}
			break;
		}
		if (mrvl_patterns[j].pattern_type == RTE_FLOW_ITEM_TYPE_END) {
			rte_flow_error_set(error, ENOTSUP,
					   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
					   "Unsupported pattern");
			return -rte_errno;
		}
	}

	flow->table_key.num_fields = flow->rule.num_fields;

	return 0;
}

/**
 * Parse flow actions.
 *
 * @param priv Pointer to the port's private data.
 * @param actions Pointer the action table.
 * @param flow Pointer to the flow.
 * @param error Pointer to the flow error.
 * @returns 0 in case of success, negative value otherwise.
 */
static int
mrvl_flow_parse_actions(struct mrvl_priv *priv,
			const struct rte_flow_action actions[],
			struct rte_flow *flow,
			struct rte_flow_error *error)
{
	const struct rte_flow_action *action = actions;
	int specified = 0;

	for (; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
		if (action->type == RTE_FLOW_ACTION_TYPE_VOID)
			continue;

		if (action->type == RTE_FLOW_ACTION_TYPE_DROP) {
			flow->cos.ppio = priv->ppio;
			flow->cos.tc = 0;
			flow->action.type = PP2_CLS_TBL_ACT_DROP;
			flow->action.cos = &flow->cos;
			specified++;
		} else if (action->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
			const struct rte_flow_action_queue *q =
				(const struct rte_flow_action_queue *)
				action->conf;

			if (q->index > priv->nb_rx_queues) {
				rte_flow_error_set(error, EINVAL,
						RTE_FLOW_ERROR_TYPE_ACTION,
						NULL,
						"Queue index out of range");
				return -rte_errno;
			}

			if (priv->rxq_map[q->index].tc == MRVL_UNKNOWN_TC) {
				/*
				 * Unknown TC mapping, mapping will not have
				 * a correct queue.
				 */
				MRVL_LOG(ERR,
					"Unknown TC mapping for queue %hu eth%hhu",
					q->index, priv->ppio_id);

				rte_flow_error_set(error, EFAULT,
						RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
						NULL, NULL);
				return -rte_errno;
			}

			MRVL_LOG(DEBUG,
				"Action: Assign packets to queue %d, tc:%d, q:%d",
				q->index, priv->rxq_map[q->index].tc,
				priv->rxq_map[q->index].inq);

			flow->cos.ppio = priv->ppio;
			flow->cos.tc = priv->rxq_map[q->index].tc;
			flow->action.type = PP2_CLS_TBL_ACT_DONE;
			flow->action.cos = &flow->cos;
			specified++;
		} else if (action->type == RTE_FLOW_ACTION_TYPE_METER) {
			const struct rte_flow_action_meter *meter;
			struct mrvl_mtr *mtr;

			meter = action->conf;
			if (!meter)
				return -rte_flow_error_set(error, EINVAL,
						RTE_FLOW_ERROR_TYPE_ACTION,
						NULL, "Invalid meter\n");

			LIST_FOREACH(mtr, &priv->mtrs, next)
				if (mtr->mtr_id == meter->mtr_id)
					break;

			if (!mtr)
				return -rte_flow_error_set(error, EINVAL,
						RTE_FLOW_ERROR_TYPE_ACTION,
						NULL,
						"Meter id does not exist\n");

			if (!mtr->shared && mtr->refcnt)
				return -rte_flow_error_set(error, EPERM,
						RTE_FLOW_ERROR_TYPE_ACTION,
						NULL,
						"Meter cannot be shared\n");

			/*
			 * In case cos has already been set
			 * do not modify it.
			 */
			if (!flow->cos.ppio) {
				flow->cos.ppio = priv->ppio;
				flow->cos.tc = 0;
			}

			flow->action.type = PP2_CLS_TBL_ACT_DONE;
			flow->action.cos = &flow->cos;
			flow->action.plcr = mtr->enabled ? mtr->plcr : NULL;
			flow->mtr = mtr;
			mtr->refcnt++;
			specified++;
		} else {
			rte_flow_error_set(error, ENOTSUP,
					   RTE_FLOW_ERROR_TYPE_ACTION, NULL,
					   "Action not supported");
			return -rte_errno;
		}
	}

	if (!specified) {
		rte_flow_error_set(error, EINVAL,
				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
				   "Action not specified");
		return -rte_errno;
	}

	return 0;
}

/**
 * Parse flow attribute, pattern and actions.
 *
 * @param priv Pointer to the port's private data.
 * @param attr Pointer to the flow attribute.
 * @param pattern Pointer to the flow pattern.
 * @param actions Pointer to the flow actions.
 * @param flow Pointer to the flow.
 * @param error Pointer to the flow error.
 * @returns 0 on success, negative value otherwise.
 */
static int
mrvl_flow_parse(struct mrvl_priv *priv, const struct rte_flow_attr *attr,
		const struct rte_flow_item pattern[],
		const struct rte_flow_action actions[],
		struct rte_flow *flow,
		struct rte_flow_error *error)
{
	int ret;

	ret = mrvl_flow_parse_attr(priv, attr, flow, error);
	if (ret)
		return ret;

	ret = mrvl_flow_parse_pattern(priv, pattern, flow, error);
	if (ret)
		return ret;

	return mrvl_flow_parse_actions(priv, actions, flow, error);
}

/**
 * Get engine type for the given flow.
 *
 * @param field Pointer to the flow.
 * @returns The type of the engine.
 */
static inline enum pp2_cls_tbl_type
mrvl_engine_type(const struct rte_flow *flow)
{
	int i, size = 0;

	for (i = 0; i < flow->rule.num_fields; i++)
		size += flow->rule.fields[i].size;

	/*
	 * For maskable engine type the key size must be up to 8 bytes.
	 * For keys with size bigger than 8 bytes, engine type must
	 * be set to exact match.
	 */
	if (size > 8)
		return PP2_CLS_TBL_EXACT_MATCH;

	return PP2_CLS_TBL_MASKABLE;
}

/**
 * Create classifier table.
 *
 * @param dev Pointer to the device.
 * @param flow Pointer to the very first flow.
 * @returns 0 in case of success, negative value otherwise.
 */
static int
mrvl_create_cls_table(struct rte_eth_dev *dev, struct rte_flow *first_flow)
{
	struct mrvl_priv *priv = dev->data->dev_private;
	struct pp2_cls_tbl_key *key = &priv->cls_tbl_params.key;
	int ret;

	if (priv->cls_tbl) {
		pp2_cls_tbl_deinit(priv->cls_tbl);
		priv->cls_tbl = NULL;
	}

	memset(&priv->cls_tbl_params, 0, sizeof(priv->cls_tbl_params));

	priv->cls_tbl_params.type = mrvl_engine_type(first_flow);
	MRVL_LOG(INFO, "Setting cls search engine type to %s",
			priv->cls_tbl_params.type == PP2_CLS_TBL_EXACT_MATCH ?
			"exact" : "maskable");
	priv->cls_tbl_params.max_num_rules = MRVL_CLS_MAX_NUM_RULES;
	priv->cls_tbl_params.default_act.type = PP2_CLS_TBL_ACT_DONE;
	priv->cls_tbl_params.default_act.cos = &first_flow->cos;
	memcpy(key, &first_flow->table_key, sizeof(struct pp2_cls_tbl_key));

	ret = pp2_cls_tbl_init(&priv->cls_tbl_params, &priv->cls_tbl);

	return ret;
}

/**
 * Check whether new flow can be added to the table
 *
 * @param priv Pointer to the port's private data.
 * @param flow Pointer to the new flow.
 * @return 1 in case flow can be added, 0 otherwise.
 */
static inline int
mrvl_flow_can_be_added(struct mrvl_priv *priv, const struct rte_flow *flow)
{
	int same = memcmp(&flow->table_key, &priv->cls_tbl_params.key,
			  sizeof(struct pp2_cls_tbl_key)) == 0;

	return same && mrvl_engine_type(flow) == priv->cls_tbl_params.type;
}

/**
 * DPDK flow create callback called when flow is to be created.
 *
 * @param dev Pointer to the device.
 * @param attr Pointer to the flow attribute.
 * @param pattern Pointer to the flow pattern.
 * @param actions Pointer to the flow actions.
 * @param error Pointer to the flow error.
 * @returns Pointer to the created flow in case of success, NULL otherwise.
 */
static struct rte_flow *
mrvl_flow_create(struct rte_eth_dev *dev,
		 const struct rte_flow_attr *attr,
		 const struct rte_flow_item pattern[],
		 const struct rte_flow_action actions[],
		 struct rte_flow_error *error)
{
	struct mrvl_priv *priv = dev->data->dev_private;
	struct rte_flow *flow, *first;
	int ret;

	if (!dev->data->dev_started) {
		rte_flow_error_set(error, EINVAL,
				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
				   "Port must be started first\n");
		return NULL;
	}

	flow = rte_zmalloc_socket(NULL, sizeof(*flow), 0, rte_socket_id());
	if (!flow)
		return NULL;

	ret = mrvl_flow_parse(priv, attr, pattern, actions, flow, error);
	if (ret)
		goto out;

	/*
	 * Four cases here:
	 *
	 * 1. In case table does not exist - create one.
	 * 2. In case table exists, is empty and new flow cannot be added
	 *    recreate table.
	 * 3. In case table is not empty and new flow matches table format
	 *    add it.
	 * 4. Otherwise flow cannot be added.
	 */
	first = LIST_FIRST(&priv->flows);
	if (!priv->cls_tbl) {
		ret = mrvl_create_cls_table(dev, flow);
	} else if (!first && !mrvl_flow_can_be_added(priv, flow)) {
		ret = mrvl_create_cls_table(dev, flow);
	} else if (mrvl_flow_can_be_added(priv, flow)) {
		ret = 0;
	} else {
		rte_flow_error_set(error, EINVAL,
				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
				   "Pattern does not match cls table format\n");
		goto out;
	}

	if (ret) {
		rte_flow_error_set(error, EINVAL,
				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
				   "Failed to create cls table\n");
		goto out;
	}

	ret = pp2_cls_tbl_add_rule(priv->cls_tbl, &flow->rule, &flow->action);
	if (ret) {
		rte_flow_error_set(error, EINVAL,
				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
				   "Failed to add rule\n");
		goto out;
	}

	LIST_INSERT_HEAD(&priv->flows, flow, next);

	return flow;
out:
	rte_free(flow);
	return NULL;
}

/**
 * Remove classifier rule associated with given flow.
 *
 * @param priv Pointer to the port's private data.
 * @param flow Pointer to the flow.
 * @param error Pointer to the flow error.
 * @returns 0 in case of success, negative value otherwise.
 */
static int
mrvl_flow_remove(struct mrvl_priv *priv, struct rte_flow *flow,
		 struct rte_flow_error *error)
{
	int ret;

	if (!priv->cls_tbl) {
		rte_flow_error_set(error, EINVAL,
				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
				   "Classifier table not initialized");
		return -rte_errno;
	}

	ret = pp2_cls_tbl_remove_rule(priv->cls_tbl, &flow->rule);
	if (ret) {
		rte_flow_error_set(error, EINVAL,
				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
				   "Failed to remove rule");
		return -rte_errno;
	}

	mrvl_free_all_key_mask(&flow->rule);

	if (flow->mtr) {
		flow->mtr->refcnt--;
		flow->mtr = NULL;
	}

	return 0;
}

/**
 * DPDK flow destroy callback called when flow is to be removed.
 *
 * @param dev Pointer to the device.
 * @param flow Pointer to the flow.
 * @param error Pointer to the flow error.
 * @returns 0 in case of success, negative value otherwise.
 */
static int
mrvl_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,
		  struct rte_flow_error *error)
{
	struct mrvl_priv *priv = dev->data->dev_private;
	struct rte_flow *f;
	int ret;

	LIST_FOREACH(f, &priv->flows, next) {
		if (f == flow)
			break;
	}

	if (!flow) {
		rte_flow_error_set(error, EINVAL,
				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
				   "Rule was not found");
		return -rte_errno;
	}

	LIST_REMOVE(f, next);

	ret = mrvl_flow_remove(priv, flow, error);
	if (ret)
		return ret;

	rte_free(flow);

	return 0;
}

/**
 * DPDK flow callback called to verify given attribute, pattern and actions.
 *
 * @param dev Pointer to the device.
 * @param attr Pointer to the flow attribute.
 * @param pattern Pointer to the flow pattern.
 * @param actions Pointer to the flow actions.
 * @param error Pointer to the flow error.
 * @returns 0 on success, negative value otherwise.
 */
static int
mrvl_flow_validate(struct rte_eth_dev *dev,
		   const struct rte_flow_attr *attr,
		   const struct rte_flow_item pattern[],
		   const struct rte_flow_action actions[],
		   struct rte_flow_error *error)
{
	static struct rte_flow *flow;

	flow = mrvl_flow_create(dev, attr, pattern, actions, error);
	if (!flow)
		return -rte_errno;

	mrvl_flow_destroy(dev, flow, error);

	return 0;
}

/**
 * DPDK flow flush callback called when flows are to be flushed.
 *
 * @param dev Pointer to the device.
 * @param error Pointer to the flow error.
 * @returns 0 in case of success, negative value otherwise.
 */
static int
mrvl_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
{
	struct mrvl_priv *priv = dev->data->dev_private;

	while (!LIST_EMPTY(&priv->flows)) {
		struct rte_flow *flow = LIST_FIRST(&priv->flows);
		int ret = mrvl_flow_remove(priv, flow, error);
		if (ret)
			return ret;

		LIST_REMOVE(flow, next);
		rte_free(flow);
	}

	if (priv->cls_tbl) {
		pp2_cls_tbl_deinit(priv->cls_tbl);
		priv->cls_tbl = NULL;
	}

	return 0;
}

/**
 * DPDK flow isolate callback called to isolate port.
 *
 * @param dev Pointer to the device.
 * @param enable Pass 0/1 to disable/enable port isolation.
 * @param error Pointer to the flow error.
 * @returns 0 in case of success, negative value otherwise.
 */
static int
mrvl_flow_isolate(struct rte_eth_dev *dev, int enable,
		  struct rte_flow_error *error)
{
	struct mrvl_priv *priv = dev->data->dev_private;

	if (dev->data->dev_started) {
		rte_flow_error_set(error, EBUSY,
				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
				   NULL, "Port must be stopped first\n");
		return -rte_errno;
	}

	priv->isolated = enable;

	return 0;
}

const struct rte_flow_ops mrvl_flow_ops = {
	.validate = mrvl_flow_validate,
	.create = mrvl_flow_create,
	.destroy = mrvl_flow_destroy,
	.flush = mrvl_flow_flush,
	.isolate = mrvl_flow_isolate
};

/**
 * Initialize flow resources.
 *
 * @param dev Pointer to the device.
 */
void
mrvl_flow_init(struct rte_eth_dev *dev)
{
	struct mrvl_priv *priv = dev->data->dev_private;

	LIST_INIT(&priv->flows);
}

/**
 * Cleanup flow resources.
 *
 * @param dev Pointer to the device.
 */
void
mrvl_flow_deinit(struct rte_eth_dev *dev)
{
	mrvl_flow_flush(dev, NULL);
}


text:
<!DOCTYPE html>

    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>pilot.user.atlas.loopingjob_definitions — Pilot 2  documentation</title>
    <link rel="stylesheet" href="../../../../_static/pygments.css" type="text/css" />
    <link rel="stylesheet" href="../../../../_static/alabaster.css" type="text/css" />

    <link rel="index" title="Index" href="../../../../genindex.html" />
    <link rel="search" title="Search" href="../../../../search.html" />

  <link rel="stylesheet" href="../../../../_static/custom.css" type="text/css" />

  <meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />

Source code for pilot.user.atlas.loopingjob_definitions

#!/usr/bin/env python
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Authors:
# - Paul Nilsson, paul.nilsson@cern.ch, 2018

[docs]def allow_loopingjob_detection():
    """
    Should the looping job detection algorithm be allowed?
    The looping job detection algorithm finds recently touched files within the job's workdir. If a found file has not
    been touched during the allowed time limit (see looping job section in util/default.cfg), the algorithm will kill
    the job/payload process.

    :return: boolean.
    """

    return True

[docs]def remove_unwanted_files(workdir, files):
    """
    Remove files from the list that are to be ignored by the looping job algorithm.

    :param workdir: working directory (string). Needed in case the find command includes the workdir in the list of
    recently touched files.
    :param files: list of recently touched files (file names).
    :return: filtered files list.
    """

    _files = []
    for _file in files:
        if not (workdir == _file or
                "workDir" in _file or
                "prmon" in _file or
                "/pilot" in _file or
                "/pandawnutil" in _file or
                "pilotlog" in _file or
                ".lib.tgz" in _file or
                ".py" in _file or
                "PoolFileCatalog" in _file or
                "setup.sh" in _file or
                "pandaJob" in _file or
                "runjob" in _file or
                "memory_" in _file or
                "mem." in _file or
                "DBRelease-" in _file):
            _files.append(_file)

    return _files

Pilot 2

Navigation

Getting started

Components

Related Topics

Documentation overview

Module code

Quick search

    <form class="search" action="../../../../search.html" method="get">
      <input type="text" name="q" aria-labelledby="searchlabel" />
      <input type="submit" value="Go" />
    </form>

      ©2017, Paul Nilsson, Mario Lassnig, Daniil Drizhuk, ....

      |
      Powered by Sphinx 3.5.4
      & Alabaster 0.7.12

redpajama_set_name: RedPajamaGithub


text:
import {Transaction} from './transaction';
import {Person} from './person';

export class Compensation extends Transaction {
  public static fromDto(dto: any): Compensation {
    return new Compensation(
      parseInt(dto.id, 10),
      Person.fromDto(dto.payer),
      parseInt(dto.amount, 10),
      Person.fromDto(dto.profiteer),
      new Date(dto['create-time']),
      new Date(dto['update-time'])
    );
  }

  constructor(id: number,
              payer: Person,
              amount: number,
              public profiteer: Person,
              createdTime?: Date,
              modifiedTime?: Date) {
    super(id, payer, amount, createdTime, modifiedTime);
  }

  public isValid(): boolean {
    return this.amount > 0
      && this.payer !== null
      && this.profiteer !== null;
  }
}


text:
package com.github.mkjensen.dml.ondemand;

import static com.github.mkjensen.dml.ondemand.OnDemandListeners.createOnItemViewClickedListener;
import static com.github.mkjensen.dml.ondemand.OnDemandListeners.createOnItemViewSelectedListener;
import static com.github.mkjensen.dml.ondemand.OnDemandListeners.createOnSearchClickedListener;

import android.os.Bundle;
import android.support.v17.leanback.app.BrowseSupportFragment;
import android.support.v17.leanback.widget.ArrayObjectAdapter;
import android.support.v17.leanback.widget.ListRow;
import android.support.v17.leanback.widget.ListRowPresenter;
import android.support.v17.leanback.widget.SinglePresenterSelector;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.util.Log;

import com.github.mkjensen.dml.R;
import com.github.mkjensen.dml.backend.loader.CategoriesLoader;
import com.github.mkjensen.dml.model.Category;
import com.github.mkjensen.dml.model.IconHeaderItem;
import com.github.mkjensen.dml.model.SettingsItem;
import com.github.mkjensen.dml.presenter.IconHeaderItemPresenter;
import com.github.mkjensen.dml.presenter.SettingsItemPresenter;
import com.github.mkjensen.dml.presenter.VideoPresenter;
import com.github.mkjensen.dml.util.LoadingHelper;

import java.util.List;

/**
 * Browse screen for on-demand videos.
 */
public final class BrowseFragment extends BrowseSupportFragment
    implements LoaderManager.LoaderCallbacks<List<Category>> {

  private static final String TAG = "BrowseFragment";

  private ArrayObjectAdapter rows;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    Log.d(TAG, "onCreate");
    super.onCreate(savedInstanceState);
    LoadingHelper.showLoading(this);
    initUi();
    initListeners();
    initLoader();
  }

  private void initUi() {
    rows = new ArrayObjectAdapter(new ListRowPresenter());
    setAdapter(rows);
    setTitle(getString(R.string.app_name));
    setHeaderPresenterSelector(new SinglePresenterSelector(new IconHeaderItemPresenter()));
    enableRowScaling(false);
  }

  private void initListeners() {
    FragmentActivity activity = getActivity();
    setOnItemViewClickedListener(createOnItemViewClickedListener(activity));
    setOnItemViewSelectedListener(createOnItemViewSelectedListener(activity));
    setOnSearchClickedListener(createOnSearchClickedListener(activity));
  }

  private void initLoader() {
    getLoaderManager().initLoader(0, null, this);
  }

  @Override
  public Loader<List<Category>> onCreateLoader(int id, Bundle args) {
    Log.d(TAG, "onCreateLoader");
    return new CategoriesLoader(getActivity());
  }

  @Override
  public void onLoadFinished(Loader<List<Category>> loader, List<Category> data) {
    Log.d(TAG, "onLoadFinished");
    LoadingHelper.hideLoading(this);
    rows.clear();
    if (data == null) {
      Log.w(TAG, "No data returned by loader");
      createSettingsRow();
      return;
    }
    for (Category category : data) {
      ListRow categoryRow = createCategoryRow(category);
      rows.add(categoryRow);
    }
    createSettingsRow();
  }

  private ListRow createCategoryRow(Category category) {
    IconHeaderItem header = new IconHeaderItem(category.getTitle(),
        R.drawable.ic_video_library_black_24dp);
    ArrayObjectAdapter adapter = new ArrayObjectAdapter(new VideoPresenter());
    adapter.addAll(0, category.getVideos());
    return new ListRow(header, adapter);
  }

  private void createSettingsRow() {
    IconHeaderItem header = new IconHeaderItem(getString(R.string.ondemand_settings),
        R.drawable.ic_settings_black_24dp);
    ArrayObjectAdapter items = new ArrayObjectAdapter(new SettingsItemPresenter());
    items.add(new SettingsItem(R.string.ondemand_settings_about,
        R.drawable.ic_info_outline_black_24dp));
    rows.add(new ListRow(header, items));
  }

  @Override
  public void onLoaderReset(Loader<List<Category>> loader) {
    Log.d(TAG, "onLoaderReset");
    rows.clear();
  }
}


text:
test_name 'C3437 - checkout a branch (file path)'

# Globals
repo_name = 'testrepo_branch_checkout'
branch = 'a_branch'

hosts.each do |host|
  tmpdir = host.tmpdir('vcsrepo')
  step 'setup - create repo' do
    install_package(host, 'git')
    my_root = File.expand_path(File.join(File.dirname(__FILE__), '../../../..'))
    scp_to(host, "#{my_root}/acceptance/files/create_git_repo.sh", tmpdir)
    on(host, "cd #{tmpdir} && ./create_git_repo.sh")
  end

  teardown do
    on(host, "rm -fr #{tmpdir}")
  end

  step 'checkout a branch with puppet' do
    pp = <<-EOS
    vcsrepo { "#{tmpdir}/#{repo_name}":
      ensure => present,
      source => "#{tmpdir}/testrepo.git",
      provider => git,
      revision => '#{branch}',
    }
    EOS

    apply_manifest_on(host, pp, :catch_failures => true)
    apply_manifest_on(host, pp, :catch_changes  => true)
  end

  step "verify checkout is on the #{branch} branch" do
    on(host, "ls #{tmpdir}/#{repo_name}/.git/") do |res|
      fail_test('checkout not found') unless res.stdout.include? "HEAD"
    end

    on(host, "cat #{tmpdir}/#{repo_name}/.git/HEAD") do |res|
      fail_test('branch not found') unless res.stdout.include? "refAdminController: refs/heads/#{branch}"
    end
  end

end


text:
<project name="HPUXConnector" default="jar" basedir=".">
  <property name="tomcat.home" value="C:\Users\mike.chung\git\HPUXConnector\HPUXConnector"/>
  <property name="lib.dir" value="${tomcat.home}\lib"/> <property name="src.dir" value="src"/>
  <property name="dest.dir" value="build/classes"/>
  <property name="jar.dir" value="build/jar"/>
  <path id="classpath">
     <fileset dir="${lib.dir}" includes="**/*.jar"/>
  </path>
  <target name="clean">
    <delete dir="build"/>
  </target>
  <target name="compile">
    <mkdir dir="${dest.dir}"/>
    <javac srcdir="${src.dir}" destdir="${dest.dir}" classpathref="classpath"
       includeantruntime="false"/>
  </target>
  <target name="jar" depends="compile">
     <mkdir dir="${jar.dir}"/>
     <jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="build/classes"/>
  </target>
  <target name="deploy" depends="jar">
     <copy file="${jar.dir}/${ant.project.name}.jar" todir="${lib.dir}"/>
     <exec executable="/bin/bash">
        <arg value="${tomcat.home}/bin/shutdown.sh"/>
     </exec>
     <exec executable="/bin/bash">
       <arg value="${tomcat.home}/bin/startup.sh"/>
    </exec>
  </target>
</project>


text:
The solutions for the course of the book:
[**The Elements of Computing Systems**](http://nand2tetris.org) by [Noam Nisan](http://www.cs.huji.ac.il/~noam) and [Shimon Schocken](http://shimonschocken.com/)


text:
/**
 * Created with JetBrains WebStorm.
 * User: kobrigo
 * Date: 12/04/13
 * Time: 23:50
 * To change this template use File | Settings | File Templates.
 */
var express = require('express');
var path = require('path');
var socketIo = require('socket.io');
var PongGame = require('./game');
var Player = require('./player');
var _ = require('lodash-node');

var consts = {
	webServerPort: 80,
	timeoutToEnterTheGameScreen: 30000
};

var pathToServe = path.normalize(path.join(__dirname, './../static/'));
var phaserPath = path.normalize(path.join(__dirname, './../../phaser/'));

var appWS = express();
var server = require('http').createServer(appWS);
var io = socketIo.listen(server);
console.log("Serving: " + pathToServe + " on port:" + consts.webServerPort);
appWS.use(function(req, res, next) {
	res.header('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0');
	next();
});
appWS.use("/", express.static(pathToServe));
appWS.use("/", express.static(phaserPath));
server.listen(consts.webServerPort);

var chatMessageId = 0;
/**
 * This counter will be used to create a unique room number for two players to play with one another.
 * @type {number}
 */
var gameRooomId = 0;
var games = {};

function getAllPlayersData() {
	var playersData = [];
	var allClients = io.sockets.clients('lobby');
	for (var i = 0, length = allClients.length; i < length; i++) {
		var currentSocket = allClients[i];
		playersData.push({nickname: currentSocket.player.nickname});
	}

	return playersData;
}

io.sockets.on('connection', function(socket) {

	socket.on('login', function(data) {
		var player = new Player(socket, data.nickname);
		//overload the player on the socket itself.
		socket.player = player;

		//Check for the nick name on all the sockets connected
		var allClients = io.sockets.clients('lobby');
		for (var i = 0, length = allClients.length; i < length; i++) {
			var currentSocket = allClients[i];
			if ((currentSocket !== socket) && //skip ourselves in the list of all sockets
				currentSocket.player.nickname === socket.player.nickname) {
				//this mean that this nick name is already taken
				player.socket.emit('login-error', {reason: 'Nickname is already taken.'});
				return;
			}
		}

		socket.emit('login-ok');
	});

	socket.on('enter-lobby', function() {
		//add the socket to the lobby before broadcasting all the data.
		socket.join('lobby');

		if (socket.player) {
			//allow only player that passed the login stage to enter the lobby (this should be blocked in the client too)

			//let all the other players in the lobby that there is a new player by sending the the updated
			//list of players.
			io.sockets.in('lobby').emit('player-joined', socket.player.nickname);

			var playersData = getAllPlayersData();
			io.sockets.in('lobby').emit('players', playersData);

			socket.emit('enter-lobby-ok', playersData);
		}
	});

	socket.on('disconnect', function() {
		console.log('disconnected from player id: ' + socket.id);
		//TODO:
		//1. if there is a game with this player find close the game deleting the game instance
		//2. move the player that is still connected to the lobby.
		if (socket.player) {
			//we could have a socket that is not logged in yet and is being disconnected.
			io.sockets.in('lobby').emit('player-left', socket.player.nickname);
		}

		//update all the player that a player has left (those that are in the lobby)
		setTimeout(function() {
			var playersData = getAllPlayersData();
			io.sockets.in('lobby').emit('players', playersData);
		}, 0)
	});

	socket.on('player-send-chat-message', function(message) {

		io.sockets.in('lobby').emit('player-chat-message', {
			nickname: socket.player.nickname,
			message: message,
			id: chatMessageId
		});

		chatMessageId++;
	});

	/**
	 * {string} data.opposedPlayerNickname the nickname of the player that this player has asked to play with
	 */
	socket.on('request-to-play', function(data) {
		//TODO: just as a percussion check that the client did not hack the code and trying to play against itself
		//find the player that this player wants to play with.
		var socketOfPlayerToPlayWith = _.find(io.sockets.clients('lobby'), function(currentSocket) {
			return currentSocket.player.nickname === data.opposedPlayerNickname;
		});

		if (_.isEmpty(socketOfPlayerToPlayWith)) {
			socket.emit('request-to-play-error', 'could not find the player ' + data.opposedPlayerNickname + ' you asked to play with in the lobby');
		}
		// remove it from the lobby
		socketOfPlayerToPlayWith.leave('lobby');
		socket.leave('lobby');
		//create a game room for them to play with one another.
		++gameRooomId;
		var gameId = 'game' + gameRooomId;
		socket.join(gameId);
		socketOfPlayerToPlayWith.join(gameId);

		//Create a game instance with these tow players.
		var game = new PongGame({
			io:io,
			initiatorPlayer: socket.player,
			opposedPlayer: socketOfPlayerToPlayWith.player,
			id: gameId
		});

		//Add the Game instance to the active list of games that will be shown in the lobby.
		games[gameId] = game;

		//send a message to the players and wait for them to enter the game screen.
		io.sockets.in(gameId).emit("request-to-play-ok");

		//set a timeout of 30 seconds if both them did not enter the room by then pop them out of the game back to the lobby
		setTimeout(function() {
			if (game.playersInTheGameScreen < 2) {
				//throw them back to the lobby and destroy the game
				game.destroy();
				delete games.gameId;
			}
		}, consts.timeoutToEnterTheGameScreen);

		console.log(game.initiatorPlayer.nickname + 'and ' + game.opposedPlayer.nickname + 'entered game room:' + game.id);
		//TODO add the active list of games in the lobby in the client side.
	});

	socket.on('client-message', function(data) {
		console.log(data);
	});

});


text:
require "rom/core"

RSpec.describe ROM, ".components" do
  let(:components) do
    ROM.components
  end

  around do |example|
    components.keys.tap do |keys|
      example.run
      (components.keys - keys).each { |key| components._container.delete(key) }
    end
  end

  it "registers a component handler with default key and namespace" do
    module Test
      class Serializer
      end
    end

    ROM.components do
      register(:serializer, Test::Serializer)
    end

    expect(components[:serializer].key).to be(:serializer)
    expect(components[:serializer].namespace).to be(:serializers)
    expect(components[:serializer].constant).to be(Test::Serializer)
  end
end


text:
/**
 * Makes a combobox of fields where only the fields shared by all the provided models are shown
 *
 */

 Ext.define('Rally.technicalservices.MultiModelFieldComboBox', {
    requires: [],
    extend: 'Rally.ui.combobox.FieldComboBox',
    alias: 'widget.tsmultimodelfieldcombobox',

    config: {
        /**
         * @cfg [{Rally.data.Model/String}] model (required) The models containing the specified field used to populate the store.
         */
        models: []
    },
    constructor: function(config) {
        this.mergeConfig(config);

        this.store = Ext.create('Ext.data.Store', {
            fields: [this.valueField, this.displayField, 'fieldDefinition'],
            data: []
        });

        return this.callParent([this.config]);
    },

    initComponent: function() {
        this.callParent(arguments);

        if (!Ext.isEmpty(this.models) ) {
            if (Ext.isString(this.models)) {
                this.models = this.models.split(',');
            }
            this._fetchModels();
        }
    },

    _fetchSpecificModel: function(model){
        var deferred = Ext.create('Deft.Deferred');

        Rally.data.ModelFactory.getModel({
            context: this.context,
            type: model,
            success: function(m) {
                deferred.resolve(m);
            },
            scope: this
        });

        return deferred.promise;
    },

    _fetchModels: function() {
        var promises = [];
        var me = this;

        Ext.Array.each(this.models, function(model){
            promises.push(function() {
                return me._fetchSpecificModel(model);
            });
        }, this);

        Deft.Chain.sequence(promises).then({
            scope: this,
            success: this._onModelsRetrieved,
            failure: function(msg) {
                Ext.Msg.alert("Couldn't retrieve model", msg);
            }
        });
    },

    _onModelsRetrieved: function(models) {
        this.models = models;
        this._populateStore();
    },

    _populateStore: function() {
        if (!this.store) {
            return;
        }

        var data = [];
        var fields_array = [];

        Ext.Array.each(this.models, function(model) {
            fields_array.push( Ext.Array.filter(model.getFields(), this._isNotHidden, this) );
        },this);

        console.log('fields_array', fields_array);

        data = this._getSharedPairs(fields_array);

        //data = _.sortBy(data,'name');

        console.log('data',data);

        this.store.loadRawData(data);
        this.setDefaultValue();
        this.onReady();
    },

    _getSharedPairs: function(array_of_fields_for_all_models){
        var calculations = {};

        Ext.Array.each(array_of_fields_for_all_models, function(array_of_fields_in_one_model){

            Ext.Array.each(array_of_fields_in_one_model, function(field){
                if ( Ext.isEmpty(calculations[field.name]) ) {
                    calculations[field.name] = {
                        field: field,
                        count: 0
                    };
                }

                if ( calculations[field.name].field.displayName == field.displayName ) {
                    calculations[field.name].count += 1;
                }
            });
        });

        var number_of_models = array_of_fields_for_all_models.length;

        var data = Ext.Array.pluck(
            Ext.Array.filter(Ext.Object.getValues(calculations), function(calculation){
                return calculation.count == number_of_models;
            }),
            'field'
        );

        return Ext.Array.map(data,function(field){
            return this._convertFieldToLabelValuePair(field);
        },this);
    }
});


text:
<!DOCTYPE html>

    <link rel="import" href="/views/external/import.html">

                        запит 2. Вивести дані про вироби (ціна виробу, вид виробу, назва виробу,
                        розмір виробу, вага виробу, кількість одиниць виробу,
                        одиниця виміру виробу, виробник виробу), яких є певна кількість,
                        і які виготовлені в певній країні.

                    <fieldset class="row">

                            Кількість виробів (шт)
                            <select class="form-control" id="ProductCount"></select>

                            Країна виробник
                            <select class="form-control" id="ProductCountry"></select>

                            <button type="button" class="btn btn-default col-md-12">РЕЗУЛЬТАТ</button>

                    </fieldset>

                    <fieldset>

                    </fieldset>


text:
react-webring
==================

A ReactJS-based web ring widget


text:
set -x
set -e

export PYTHONUNBUFFERED="True"

LOG="experiments/logs/shapenet_scene_vgg16_color.txt.`date +'%Y-%m-%d_%H-%M-%S'`"
exec &> >(tee -a "$LOG")
echo Logging output to "$LOG"

#time ./tools/train_net.py --gpu $1 \
#  --solver models/VGG16/shapenet_scene/solver_color.prototxt \
#  --weights data/imagenet_models/VGG16.v2.caffemodel \
#  --imdb shapenet_scene_train \
#  --cfg experiments/cfgs/shapenet_scene.yml \
#  --iters 40000

time ./tools/test_net.py --gpu $1 \
  --def models/VGG16/shapenet_scene/test_color.prototxt \
  --net output/shapenet_scene/shapenet_scene_train/vgg16_ism_color_shapenet_scene_iter_40000.caffemodel \
  --imdb shapenet_scene_val \
  --cfg experiments/cfgs/shapenet_scene.yml


text:
package org.apache.camel.processor.routingslip;

import org.apache.camel.Body;
import org.apache.camel.CamelContext;
import org.apache.camel.ContextTestSupport;
import org.apache.camel.Exchange;
import org.apache.camel.Header;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.spi.CamelEvent;
import org.apache.camel.spi.CamelEvent.ExchangeSendingEvent;
import org.apache.camel.spi.CamelEvent.ExchangeSentEvent;
import org.apache.camel.support.EventNotifierSupport;
import org.junit.Test;

public class DynamicRouterEventNotifierTest extends ContextTestSupport {

    private MyEventNotifier notifier = new MyEventNotifier();

    @Override
    protected CamelContext createCamelContext() throws Exception {
        CamelContext context = super.createCamelContext();
        context.getManagementStrategy().addEventNotifier(notifier);
        return context;
    }

    @Test
    public void testDynamicRouterEventNotifier() throws Exception {
        getMockEndpoint("mock:x").expectedMessageCount(1);
        getMockEndpoint("mock:y").expectedMessageCount(1);
        getMockEndpoint("mock:z").expectedMessageCount(1);
        getMockEndpoint("mock:end").expectedMessageCount(1);

        template.sendBody("direct:start", "Hello World");

        assertMockEndpointsSatisfied();

        assertEquals("Should have 5 sending events", 5, notifier.getSending());
        assertEquals("Should have 5 sent events", 5, notifier.getSent());
    }

    @Override
    protected RouteBuilder createRouteBuilder() {
        return new RouteBuilder() {
            public void configure() {
                from("direct:start").dynamicRouter(method(DynamicRouterEventNotifierTest.class, "slip")).to("mock:end");
            }
        };
    }

    public String slip(@Body String body, @Header(Exchange.SLIP_ENDPOINT) String previous) {
        if (previous == null) {
            return "mock:x";
        } else if ("mock://x".equals(previous)) {
            return "mock:y";
        } else if ("mock://y".equals(previous)) {
            return "mock:z";
        }

        // no more so return null
        return null;
    }

    private final class MyEventNotifier extends EventNotifierSupport {

        private int sending;
        private int sent;

        @Override
        public void notify(CamelEvent event) throws Exception {
            if (event instanceof ExchangeSendingEvent) {
                log.info("Sending: {}", event);
                sending++;
            } else {
                sent++;
            }
        }

        @Override
        public boolean isEnabled(CamelEvent event) {
            return event instanceof ExchangeSendingEvent || event instanceof ExchangeSentEvent;
        }

        public int getSending() {
            return sending;
        }

        public int getSent() {
            return sent;
        }
    }
}


text:
import json
from collections import  defaultdict
from test.test_trace import TestLineCounts
from pandas import DataFrame,Series
import pandas as pd; import numpy as np
from collections import Counter
import matplotlib.pyplot as plt
class DataMining:
    __path = 'D:\software\Python\python code\pydata-book-master' ;
    __record = [];
    def __init__(self,path):
        print('path:'+path)
        self.__path = path;
        self.__record = [json.loads(line) for line in open(path)];

    def getCounts(self,sequence):
        counts = {}
        for x in sequence:
            if x in counts:
                counts[x] += 1
            else:
                counts[x] = 1
        return counts

    def getCountsByPythonLibrary(self,sequence):
        counts = defaultdict(int)
        for x in sequence:
            counts[x] += 1
        return counts

    def getTopCounts(self,count_dict,n = 10):
        value_key_pairs = [(count,tz) for tz,count in count_dict.items()]
        value_key_pairs.sort()
        return value_key_pairs[-n:]

    def ch02(self):
        print("ch02 starting!")
        print(self.__record[0])
        print("self.__record[0]['tz']:"+self.__record[0]['tz'])
        time_zones = [rec['tz'] for rec in self.__record if 'tz' in rec]
        print("time_zones[:10]")
        print(time_zones[:10])
        counts = self.getCountsByPythonLibrary(time_zones)
        print(counts)
        print(counts["America/New_York"])
        print("len:")
        len(time_zones)
        print("get Top counts:")
        print(self.getTopCounts(counts))
        counts = Counter(time_zones)
        print("get Top Counts By libray Func:")
        counts.most_common(10)

    def ch02_frame(self):
        print("ch03 starting")
        frame = DataFrame(self.__record);
#         print(frame)
        tz_counts = frame['tz'].value_counts();
#         print( tz_counts[:10])
        clean_tz = frame['tz'].fillna('Missing');
        clean_tz[clean_tz == ''] = 'unknown'
        tz_counts = clean_tz.value_counts()
#         print(tz_counts[:10])
#         print(tz_counts[:10].plot(kind='barh',rot=0))
        results = Series([])

#         print(frame['_heartbeat_'])
        print('operating_system:')
        operating_system = np.where(frame['a'].str.contains('windows'))
        print(operating_system)
#         print(results)
    def drawPlot(self):
        x = np.linspace(0, 10, 1000)
        y = np.sin(x)
        z = np.cos(x**2)

        plt.figure(figsize=(10,6))
        plt.plot(x,y,label="$sin(x)$",color="red",linewidth=2)
        plt.plot(x,z,"b--",label="$cos(x^2)$")
        plt.xlabel("Time(s)")
        plt.ylabel("Volt")
        plt.title("PyPlot First Example")
        plt.ylim(-1.2,1.2)
        plt.legend()
        plt.show()
    def plotTest(self):
        plt.figure()
        plt.xlabel('xLabel')
        plt.ylabel('yLabel')
        plt.title('title')
        x=[1,2,3]
        y=[4,5,6]
        plt.plot(x,y)
        plt.show()


text:
package com.meltmedia.cadmium.core.commands;

import com.meltmedia.cadmium.core.messaging.ChannelMember;
import com.meltmedia.cadmium.core.messaging.Message;

import java.util.HashMap;
import java.util.Map;

public abstract class AbstractCommandResponse<T> implements CommandResponse<T> {

  protected Map<ChannelMember, Message<T>> responses = new HashMap<ChannelMember, Message<T>>();

  @Override
  public Message<T> getResponse(ChannelMember member) {
    if(responses.containsKey(member)) {
      return responses.get(member);
    }
    return null;
  }

  @Override
  public void reset(ChannelMember member) {
    if(responses.containsKey(member)) {
      responses.remove(member);
    }
  }

  @Override
  public void resetAll() {
    responses.clear();
  }

}


text:
import {
	Component,
	PropTypes
} from 'react';

import Radium from 'radium';

import { yellow500 } from 'material-ui/styles/colors';

import Icon from 'components/Icon';
import { Link } from 'react-router';

const styles = {
	container: {
		display: 'inline-block',
		padding: 10,
		WebkitAppRegion: 'no-drag'
	},
	book: {
		display: 'flex',
		flexDirection: 'column',
		textAlign: 'center'
	},
	link: {
		color: 'white',
		fontSize: 16,
		width: 195,
		textDecoration: 'none'
	},
	image: {
		width: 195,
		height: 260
	},
	starButton: {
		fontSize: '40px',
		cursor: 'pointer',
		color: yellow500
	},
	starred: {
		color: yellow500
	},
	starButtonContainer: {
		position: 'absolute',
		marginLeft: '150px'
	}
};

@Radium
export default class ComicBook extends Component {
	static propTypes = {
		coverImage: PropTypes.string,
		latestChapter: PropTypes.string,
		comicName: PropTypes.string,
		starred: PropTypes.bool,
		onStarButtonClick: PropTypes.func,

		showStarButton: PropTypes.bool
	}

	static defaultProps = {
		showStarButton: true
	}

	iconName = () => this.props.starred ? 'star' : 'star_border';

	iconStyle = () => this.props.starred ? styles.starred : { };

	renderStarButton = () => {
		const { onStarButtonClick } = this.props;

		return(
			<Icon
				iconName={this.iconName()}
				style={{
					...styles.starButton,
					...this.iconStyle()
				}}
				onClick={onStarButtonClick}
			/>
		);
	}

	render() {
		const {
			coverImage,
			latestChapter,
			comicName,
			showStarButton
		} = this.props;

		return(

					{ showStarButton ? this.renderStarButton() : null }

					<Link to={`/reader/dm5/${latestChapter}`}>

					</Link>
					<Link to={`/reader/dm5/${latestChapter}`} style={styles.link}>
						{comicName}
					</Link>

		);
	}
}


text:
\section{/home/silas/\+Idea\+Projects/\+En\+Ocean/src/ch/bfh/gr33nopo55um/enocean/helper/\+Read\+Config.java File Reference}
\label{ReadConfig_8java}\index{/home/silas/\+Idea\+Projects/\+En\+Ocean/src/ch/bfh/gr33nopo55um/enocean/helper/\+Read\+Config.\+java@{/home/silas/\+Idea\+Projects/\+En\+Ocean/src/ch/bfh/gr33nopo55um/enocean/helper/\+Read\+Config.\+java}}
\subsection*{Classes}
\begin{DoxyCompactItemize}
\item
class {\bf Read\+Config}
\end{DoxyCompactItemize}
\subsection*{Packages}
\begin{DoxyCompactItemize}
\item
package {\bf ch.\+bfh.\+gr33nopo55um.\+enocean.\+helper}
\end{DoxyCompactItemize}


text:
package ucesoft.cbm.misc

import ucesoft.cbm.{CBMComponent, CBMComponentType}
import ucesoft.cbm.CBMComponentType.Type

import java.awt._
import java.io.{ObjectInputStream, ObjectOutputStream}
import java.util.Properties
import javax.swing.{JComponent, JLabel}

class DriveLed(id:Int) extends JComponent with CBMComponent {
  val componentID = "Drive led"
  val componentType: Type = CBMComponentType.INTERNAL
  var powerOn,driveLedOn,driveWriteMode = false

  private[this] final val LED_OFF = Color.DARK_GRAY
  private[this] final val LED_READ_ON = Color.RED
  private[this] final val LED_WRITE_ON = Color.ORANGE
  private[this] final val POWER_LED_ON = Color.RED
  private[this] final val POWER_ACCESS_LED_ON = Color.GREEN
  private[this] var powerLedMode = false
  private[this] val label = new JLabel("")

  setLayout(new FlowLayout(FlowLayout.LEFT))
  add(new JLabel("%2d:".format(id)))
  add(new Led)
  add(label)

  def setPowerLedMode(on:Boolean): Unit = {
    powerLedMode = on
    repaint()
  }

  def showLedInfo(info:String) : Unit = {
    label.setText("%s".format(info))
  }

  private class Led extends JComponent {
    setPreferredSize(new Dimension(15,15))
    override def paint(g:Graphics) : Unit = {
      if (powerLedMode) {
        val size = getSize()
        g.setColor(Color.GRAY)
        g.fillRect(1,1,size.width - 1,size.height - 1)
        val height = size.height
        size.height = (size.height * 0.5).toInt
        val midH = height - size.height
        drawLed(powerOn,0,0,g,size,true,POWER_LED_ON)
        drawLed(driveLedOn,0,midH,g,size,false,POWER_ACCESS_LED_ON)
      }
      else {
        drawLed(driveLedOn,0,0,g,getSize,false,LED_READ_ON)
      }
    }

    private def drawLed(on:Boolean,x:Int,y:Int,g:Graphics,size:Dimension,isPowerLed:Boolean,ledColor:Color) : Unit = {
      val size = getSize()
      val g2 = g.asInstanceOf[Graphics2D]
      g2.setColor(Color.BLACK)
      g2.drawRect(x,y,size.width - 1,size.height - 1)
      val color = if (on) {
        if (isPowerLed) POWER_LED_ON
        else
          if (driveWriteMode) LED_WRITE_ON
          else ledColor
      }
      else Color.DARK_GRAY
      g2.setColor(color)
      g2.fillRect(x + 1,y + 1,size.width - 1,size.height - 1)
    }
  }

  override def getProperties: Properties = {
    properties.setProperty("Led on",driveLedOn.toString)
    properties
  }

  def init  : Unit = {}
  def reset  : Unit = {}
  // state
  protected def saveState(out:ObjectOutputStream) : Unit = {
    out.writeBoolean(powerOn)
    out.writeBoolean(driveLedOn)
    out.writeBoolean(driveWriteMode)
    out.writeBoolean(powerLedMode)
  }
  protected def loadState(in:ObjectInputStream) : Unit = {
    powerOn = in.readBoolean
    driveLedOn = in.readBoolean
    driveWriteMode = in.readBoolean
    powerLedMode = in.readBoolean
  }
  protected def allowsStateRestoring : Boolean = true
}


text:
from django.urls import reverse_lazy
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import tables
from horizon.utils import memoized

from nuage_horizon.api import neutron
from nuage_horizon.dashboards.project.gateways.ports.vlans import \
    tables as vlan_tables

class DetailView(tables.DataTableView):
    table_class = vlan_tables.VlansTable
    template_name = 'nuage/gateways/ports/detail.html'
    page_title = _("Gateway Port Details: {{ gw_port.name }}")
    failure_url = reverse_lazy('horizon:project:gateways:index')

    def get_data(self):
        request = self.request
        try:
            gw_port = self._get_gateway_port_data()
            gw_vlans = neutron.nuage_gateway_vlan_list(
                self.request, gw_port.id)
            vlans = []
            for vlan in gw_vlans:
                if vlan.get('vport'):
                    dict = vlan.to_dict()
                    vport = neutron.nuage_gateway_vport_get(request,
                                                            vlan['vport'])
                    dict['vport'] = vport
                    if vport and vport.get('subnet'):
                        subnet = neutron.subnet_get(request,
                                                    vport.get('subnet'))
                        dict['subnet'] = subnet
                        if vport.get('port'):
                            try:
                                port = neutron.port_get(request,
                                                        vport['port'])
                                dict['port'] = port
                            except Exception:
                                dict['port'] = None
                    vlan = neutron.NuageGatewayVlan(dict)
                vlans.append(vlan)
        except Exception:
            vlans = []
            msg = _('Nuage Gateway Vlan list can not be retrieved.')
            exceptions.handle(request, msg)
        return vlans

    @memoized.memoized_method
    def _get_gateway_port_data(self):
        try:
            gw_port_id = self.kwargs['gw_port_id']
            gw_port = neutron.nuage_gateway_port_get(self.request, gw_port_id)
        except Exception:
            gw_port = None
            msg = _('Gateway Port can not be retrieved.')
            exceptions.handle(self.request, msg, redirect=self.failure_url)
        return gw_port

    def get_context_data(self, **kwargs):
        context = super(DetailView, self).get_context_data(**kwargs)
        gw_port = self._get_gateway_port_data()
        context["gw_port"] = gw_port
        context["url"] = self.get_redirect_url()
        return context

    @staticmethod
    def get_redirect_url():
        return reverse_lazy('horizon:project:gateways:index')


text:
namespace Google.Cloud.Speech.V2.Snippets
{
    // [START speech_v2_generated_Speech_DeleteRecognizer_sync_flattened_resourceNames]
    using Google.Cloud.Speech.V2;
    using Google.LongRunning;

    public sealed partial class GeneratedSpeechClientSnippets
    {
        /// <summary>Snippet for DeleteRecognizer</summary>
        /// <remarks>
        /// This snippet has been automatically generated and should be regarded as a code template only.
        /// It will require modifications to work:
        /// - It may require correct/in-range values for request initialization.
        /// - It may require specifying regional endpoints when creating the service client as shown in
        ///   https://cloud.google.com/dotnet/docs/reference/help/client-configuration#endpoint.
        /// </remarks>
        public void DeleteRecognizerResourceNames()
        {
            // Create client
            SpeechClient speechClient = SpeechClient.Create();
            // Initialize request argument(s)
            RecognizerName name = RecognizerName.FromProjectLocationRecognizer("[PROJECT]", "[LOCATION]", "[RECOGNIZER]");
            // Make the request
            Operation<Recognizer, OperationMetadata> response = speechClient.DeleteRecognizer(name);

            // Poll until the returned long-running operation is complete
            Operation<Recognizer, OperationMetadata> completedResponse = response.PollUntilCompleted();
            // Retrieve the operation result
            Recognizer result = completedResponse.Result;

            // Or get the name of the operation
            string operationName = response.Name;
            // This name can be stored, then the long-running operation retrieved later by name
            Operation<Recognizer, OperationMetadata> retrievedResponse = speechClient.PollOnceDeleteRecognizer(operationName);
            // Check if the retrieved long-running operation has completed
            if (retrievedResponse.IsCompleted)
            {
                // If it has completed, then access the result
                Recognizer retrievedResult = retrievedResponse.Result;
            }
        }
    }
    // [END speech_v2_generated_Speech_DeleteRecognizer_sync_flattened_resourceNames]
}


text:
import { STARTTAG_REX, ENDTAG_REX }from './regexp'
import { isEmptyMaker } from './makers'
import { TagStart, TagEmpty, TagEnd, Text} from './types'

export function tokenize(html) {
  let string = html
  let tokens = []
  const maxTime = Date.now() + 1000

  while (string) {
    if (string.indexOf("<!--") === 0) {
      const lastIndex = string.indexOf("-->") + 3
      string = string.substring(lastIndex)
      continue
    }
    if (string.indexOf("</") === 0) {
      const match = string.match(ENDTAG_REX)
      if (!match) continue
      string = string.substring(match[0].length)
      const name = match[1]
      if (isEmptyMaker(name)) continue

      tokens.push(new TagEnd(name))
      continue
    }
    if (string.indexOf("<") === 0) {
      const match = string.match(STARTTAG_REX)
      if (!match) continue
      string = string.substring(match[0].length)
      const name = match[1]
      const attrs = match[2]
      const token = isEmptyMaker(name) ? new TagEmpty(name, attrs) : new TagStart(name, attrs)

      tokens.push(token)
      continue
    }

    const index = string.indexOf('<')
    const text = index < 0 ? string : string.substring(0, index)

    string = index < 0 ? "" : string.substring(index)
    tokens.push(new Text(text))

    if (Date.now() >= maxTime) break
  }
  return tokens
}


text:
ACCEPTED

#### According to
The Catalogue of Life, 3rd January 2011

#### Published in
J. B. P. A. M. de Lamarck & A. P. de Candolle, Fl. franç. ed. 3, 5:597. 1815

#### Original name
null

### Remarks
null


text:
package org.objectweb.asm.tree;

import java.util.ArrayList;
import java.util.List;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ModuleVisitor;
import org.objectweb.asm.Opcodes;

/**
 * A node that represents a module declaration.
 *
 * @author Remi Forax
 */
public class ModuleNode extends ModuleVisitor {
    /**
     * A list of modules can are required by the current module.
     * May be <tt>null</tt>.
     */
    public List<ModuleRequireNode> requires;

    /**
     * A list of packages that are exported by the current module.
     * May be <tt>null</tt>.
     */
    public List<ModuleExportNode> exports;

    /**
     * A list of classes in their internal forms that are used
     * as a service by the current module. May be <tt>null</tt>.
     */
    public List<String> uses;

    /**
     * A list of services along with their implementations provided
     * by the current module. May be <tt>null</tt>.
     */
    public List<ModuleProvideNode> provides;

    public ModuleNode() {
        super(Opcodes.ASM6);
    }

    public ModuleNode(final int api,
      List<ModuleRequireNode> requires,
      List<ModuleExportNode> exports,
      List<String> uses,
      List<ModuleProvideNode> provides) {
        super(Opcodes.ASM6);
        this.requires = requires;
        this.exports = exports;
        this.uses = uses;
        this.provides = provides;
        if (getClass() != ModuleNode.class) {
            throw new IllegalStateException();
        }
    }

    @Override
    public void visitRequire(String module, int access) {
        if (requires == null) {
            requires = new ArrayList<ModuleRequireNode>(5);
        }
        requires.add(new ModuleRequireNode(module, access));
    }

    @Override
    public void visitExport(String packaze, String... modules) {
        if (exports == null) {
            exports = new ArrayList<ModuleExportNode>(5);
        }
        List<String> moduleList = null;
        if (modules != null) {
            moduleList = new ArrayList<String>(modules.length);
            for(int i = 0; i < modules.length; i++) {
                moduleList.add(modules[i]);
            }
        }
        exports.add(new ModuleExportNode(packaze, moduleList));
    }

    @Override
    public void visitUse(String service) {
        if (uses == null) {
            uses = new ArrayList<String>(5);
        }
        uses.add(service);
    }

    @Override
    public void visitProvide(String service, String impl) {
        if (provides == null) {
            provides = new ArrayList<ModuleProvideNode>(5);
        }
        provides.add(new ModuleProvideNode(service, impl));
    }

    @Override
    public void visitEnd() {
    }

    public void accept(final ClassVisitor cv) {
        ModuleVisitor mv = cv.visitModule();
        if (mv == null) {
            return;
        }
        if (requires != null) {
            for(int i = 0; i < requires.size(); i++) {
                requires.get(i).accept(mv);
            }
        }
        if (exports != null) {
            for(int i = 0; i < exports.size(); i++) {
                exports.get(i).accept(mv);
            }
        }
        if (uses != null) {
            for(int i = 0; i < uses.size(); i++) {
                mv.visitUse(uses.get(i));
            }
        }
        if (provides != null) {
            for(int i = 0; i < provides.size(); i++) {
                provides.get(i).accept(mv);
            }
        }
    }
}


text:
<?php /* Smarty version 2.6.14, created on 2007-10-11 07:58:37
         compiled from file:/home/kerrywilson/rabbitphp.org/lib/framework/elements/view_file_missing.tpl */ ?>

<?php echo $this->_tpl_vars['filename']; ?>

To put content here edit the file shown above.