[lttng-dev] [RFC Patch Ust 2/5] Serialize the CTF global structures for ust-comm

Mathieu Desnoyers mathieu.desnoyers at efficios.com
Wed Apr 9 11:42:18 EDT 2014


----- Original Message -----
> From: "Geneviève Bastien" <gbastien+lttng at versatic.net>
> To: lttng-dev at lists.lttng.org
> Sent: Wednesday, March 26, 2014 10:47:09 AM
> Subject: [lttng-dev] [RFC Patch Ust 2/5] Serialize the CTF global structures	for ust-comm
> 
> It flatten the global types so that global types used by other global types

flatten -> flattens

> all belong to the event at serialization. This avoids recursive calls to the
> send and receive functions and simplifies error handling (no recursive
> frees).

Is the structure and enum part of the event, or declared outside of
the event scope ?

Is there a downside to this approach ? For instance, if the same
structure is used in many events, do we have to send the structure info
many times ?

Thanks,

Mathieu

> 
> Signed-off-by: Geneviève Bastien <gbastien+lttng at versatic.net>
> ---
>  liblttng-ust-comm/lttng-ust-comm.c | 170
>  +++++++++++++++++++++++++++++++++----
>  liblttng-ust-ctl/ustctl.c          |  26 ++++++
>  2 files changed, 179 insertions(+), 17 deletions(-)
> 
> diff --git a/liblttng-ust-comm/lttng-ust-comm.c
> b/liblttng-ust-comm/lttng-ust-comm.c
> index bc22130..90274c4 100644
> --- a/liblttng-ust-comm/lttng-ust-comm.c
> +++ b/liblttng-ust-comm/lttng-ust-comm.c
> @@ -742,6 +742,7 @@ int serialize_basic_type(enum ustctl_abstract_types
> *uatype,
>  	}
>  	case atype_array:
>  	case atype_sequence:
> +	case atype_structure:
>  	default:
>  		return -EINVAL;
>  	}
> @@ -800,6 +801,14 @@ int serialize_one_type(struct ustctl_type *ut, const
> struct lttng_type *lt)
>  		ut->atype = ustctl_atype_sequence;
>  		break;
>  	}
> +	case atype_structure:
> +	{
> +		strncpy(ut->u.structure.name, lt->u.structure.name,
> +						LTTNG_UST_SYM_NAME_LEN);
> +		ut->u.structure.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
> +		ut->atype = ustctl_atype_structure;
> +		break;
> +	}
>  	default:
>  		return -EINVAL;
>  	}
> @@ -892,25 +901,82 @@ int serialize_enum(struct ustctl_enum *uenum,
>  }
>  
>  static
> -int serialize_global_type_decl(size_t *_nr_write_global_type_decl,
> -		struct ustctl_global_type_decl **ustctl_global_type,
> +int serialize_structure(struct ustctl_structure *ustruct,
> +		const struct lttng_structure *lstruct)
> +{
> +	int ret;
> +
> +	strncpy(ustruct->name, lstruct->name, LTTNG_UST_SYM_NAME_LEN);
> +	ustruct->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
> +
> +	/* Serialize the fields */
> +	if (lstruct->nr_fields > 0) {
> +		ret = serialize_fields(&ustruct->nr_fields, &ustruct->fields,
> +				lstruct->nr_fields,	lstruct->fields);
> +		if (ret) {
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static size_t get_child_global_type_count(size_t nr_global_type_decl,
> +		const struct lttng_global_type_decl *lttng_global_type)
> +{
> +	size_t total_global_types = 0;
> +	int i;
> +	const struct lttng_global_type_decl *lg;
> +
> +	for (i = 0; i < nr_global_type_decl; i++) {
> +		lg = &lttng_global_type[i];
> +
> +		if (lg->nowrite)
> +			continue;
> +
> +		/* Count the global types in children as well */
> +		switch (lg->mtype) {
> +		case mtype_structure:
> +		{
> +			const struct lttng_structure *ls;
> +
> +			ls = lg->u.ctf_structure;
> +			/* Add the number of global types it contains and the count of its own
> children */
> +			if (ls->nr_global_type_decl > 0) {
> +				total_global_types += ls->nr_global_type_decl;
> +				total_global_types +=
> get_child_global_type_count(ls->nr_global_type_decl,
> +								ls->global_type_decl);
> +			}
> +			break;
> +		}
> +		case mtype_enum:
> +		default:
> +			break;
> +		}
> +	}
> +
> +	return total_global_types;
> +}
> +
> +/*
> + * When this method is called, index is the next index to write to and the
> + * ustctl_global_type structure is already initialized and will not
> overflow.
> + *
> + * The global type declarations are flattened at serialization to avoid
> + * needing to do recursive frees on error.
> + */
> +static int _serialize_global_type_decl(size_t *index,
> +		struct ustctl_global_type_decl *global_type_decl,
>  		size_t nr_global_type_decl,
>  		const struct lttng_global_type_decl *lttng_global_type)
>  {
> -	struct ustctl_global_type_decl *global_type_decl;
>  	int i, ret;
> -	size_t nr_write_global_type_decl = 0;
> -
> -	global_type_decl = zmalloc(nr_global_type_decl
> -					* sizeof(*global_type_decl));
> -	if (!global_type_decl)
> -		return -ENOMEM;
>  
>  	for (i = 0; i < nr_global_type_decl; i++) {
>  		struct ustctl_global_type_decl *f;
>  		const struct lttng_global_type_decl *lf;
>  
> -		f = &global_type_decl[nr_write_global_type_decl];
> +		f = &global_type_decl[*index];
>  		lf = &lttng_global_type[i];
>  
>  		/* skip 'nowrite' fields */
> @@ -928,18 +994,66 @@ int serialize_global_type_decl(size_t
> *_nr_write_global_type_decl,
>  			le = lf->u.ctf_enum;
>  			ret = serialize_enum(ue, le);
>  			if (ret)
> -				goto error;
> +				return ret;
>  
>  			f->mtype = ustctl_mtype_enum;
>  			break;
>  		}
> +		case mtype_structure:
> +		{
> +			struct ustctl_structure *us;
> +			const struct lttng_structure *ls;
> +
> +			/* Serialize children global types first */
> +			ls = lf->u.ctf_structure;
> +			ret = _serialize_global_type_decl(index,
> +					global_type_decl,
> +					ls->nr_global_type_decl,
> +					ls->global_type_decl);
> +			if (ret)
> +				return ret;
> +
> +			/* Reinitialize f since the index may have changed */
> +			f = &global_type_decl[*index];
> +			us = &f->u.ctf_structure;
> +
> +			ret = serialize_structure(us, ls);
> +			if (ret)
> +				return ret;
> +
> +			f->mtype = ustctl_mtype_structure;
> +			break;
> +		}
>  		default:
> -			ret = -EINVAL;
> -			goto error;
> +			return -EINVAL;
>  		}
>  
> -		nr_write_global_type_decl++;
> +		*index = *index + 1;
>  	}
> +	return 0;
> +}
> +
> +static
> +int serialize_global_type_decl(size_t *_nr_write_global_type_decl,
> +		struct ustctl_global_type_decl **ustctl_global_type,
> +		size_t nr_global_type_decl,
> +		const struct lttng_global_type_decl *lttng_global_type)
> +{
> +	struct ustctl_global_type_decl *global_type_decl;
> +	int i, ret;
> +	size_t nr_write_global_type_decl = 0;
> +	size_t nr_child_global_type_cnt =
> get_child_global_type_count(nr_global_type_decl,
> +							lttng_global_type);
> +
> +	global_type_decl = zmalloc((nr_global_type_decl + nr_child_global_type_cnt)
> +					* sizeof(*global_type_decl));
> +	if (!global_type_decl)
> +		return -ENOMEM;
> +
> +	ret = _serialize_global_type_decl(&nr_write_global_type_decl,
> global_type_decl,
> +			nr_global_type_decl, lttng_global_type);
> +	if (ret)
> +		goto error;
>  
>  	*_nr_write_global_type_decl = nr_write_global_type_decl;
>  	*ustctl_global_type = global_type_decl;
> @@ -954,6 +1068,9 @@ error:
>  		case ustctl_mtype_enum:
>  			free(m->u.ctf_enum.entries);
>  			break;
> +		case ustctl_mtype_structure:
> +			free(m->u.ctf_structure.fields);
> +			break;
>  		default:
>  			break;
>  		}
> @@ -1158,15 +1275,31 @@ int ustcomm_register_event(int sock,
>  				}
>  				break;
>  			}
> +			case ustctl_mtype_structure:
> +			{
> +				int field_len = one_global_type->u.ctf_structure.nr_fields *
> sizeof(*one_global_type->u.ctf_structure.fields);
> +
> +				/* Send the fields */
> +				DBG("Sending fields for global type structure %s.\n",
> +						one_global_type->u.ctf_structure.name);
> +				len = ustcomm_send_unix_sock(sock,
> one_global_type->u.ctf_structure.fields, field_len);
> +				free(one_global_type->u.ctf_structure.fields);
> +				one_global_type->u.ctf_structure.fields = NULL;
> +				if (len > 0 && len != field_len) {
> +					goto error_global_type;
> +				}
> +				if (len < 0) {
> +					goto error_global_type;
> +				}
> +				break;
> +			}
>  			default:
>  				break;
>  			}
>  		}
> -		free(global_type_decl);
>  
> -	} else {
> -		free(global_type_decl);
>  	}
> +	free(global_type_decl);
>  
>  	/* receive reply */
>  	len = ustcomm_recv_unix_sock(sock, &reply, sizeof(reply));
> @@ -1212,6 +1345,9 @@ error_global_type:
>  		case ustctl_mtype_enum:
>  			free(one_global_type->u.ctf_enum.entries);
>  			break;
> +		case ustctl_mtype_structure:
> +			free(one_global_type->u.ctf_structure.fields);
> +			break;
>  		default:
>  			break;
>  		}
> diff --git a/liblttng-ust-ctl/ustctl.c b/liblttng-ust-ctl/ustctl.c
> index a181e62..3100f1b 100644
> --- a/liblttng-ust-ctl/ustctl.c
> +++ b/liblttng-ust-ctl/ustctl.c
> @@ -1896,6 +1896,32 @@ int ustctl_recv_register_event(int sock,
>  				}
>  				break;
>  			}
> +			case ustctl_mtype_structure:
> +			{
> +				int entry_len = one_global_type->u.ctf_structure.nr_fields *
> sizeof(*one_global_type->u.ctf_structure.fields);
> +				/* Receive the entries */
> +				one_global_type->u.ctf_structure.fields = zmalloc(entry_len);
> +				if (!one_global_type->u.ctf_structure.fields) {
> +					len = -ENOMEM;
> +					goto global_type_error;
> +				}
> +				len = ustcomm_recv_unix_sock(sock,
> +						one_global_type->u.ctf_structure.fields,
> +						entry_len);
> +				DBG("Received fields for struct %s.\n",
> one_global_type->u.ctf_structure.name);
> +				if (len > 0 && len != entry_len) {
> +					len = -EIO;
> +					goto global_type_error;
> +				}
> +				if (len == 0) {
> +					len = -EPIPE;
> +					goto global_type_error;
> +				}
> +				if (len < 0) {
> +					goto global_type_error;
> +				}
> +				break;
> +			}
>  			default:
>  				break;
>  			}
> --
> 1.9.1
> 
> 
> _______________________________________________
> lttng-dev mailing list
> lttng-dev at lists.lttng.org
> http://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev
> 

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com



More information about the lttng-dev mailing list