aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/ext/census/resource.c
diff options
context:
space:
mode:
authorGravatar Alistair Veitch <aveitch@google.com>2016-06-07 08:59:30 -0700
committerGravatar Alistair Veitch <aveitch@google.com>2016-06-07 08:59:30 -0700
commit0cf4defa42dfd0e1f09ea3e1fae7c111a673244f (patch)
tree94bdb15572e0fab7f810cb529dd69ea095bdfabb /src/core/ext/census/resource.c
parent4eb67b47a0918f5633585cfc3335476139d37685 (diff)
simplify base resource definition; misc comment updates
Diffstat (limited to 'src/core/ext/census/resource.c')
-rw-r--r--src/core/ext/census/resource.c142
1 files changed, 100 insertions, 42 deletions
diff --git a/src/core/ext/census/resource.c b/src/core/ext/census/resource.c
index 632b899e41..0ca0db94ba 100644
--- a/src/core/ext/census/resource.c
+++ b/src/core/ext/census/resource.c
@@ -32,7 +32,6 @@
*/
#include "resource.h"
-#include "gen/census.pb.h"
#include "third_party/nanopb/pb_decode.h"
#include <grpc/census.h>
@@ -43,13 +42,6 @@
#include <stdbool.h>
#include <string.h>
-// Internal representation of a resource.
-typedef struct {
- char *name;
- // Pointer to raw protobuf used in resource definition.
- uint8_t *raw_pb;
-} resource;
-
// Protect local resource data structures.
static gpr_mu resource_lock;
@@ -65,7 +57,7 @@ static size_t n_resources = 0;
// Number of defined resources
static size_t n_defined_resources = 0;
-void initialize_resources() {
+void initialize_resources(void) {
gpr_mu_init(&resource_lock);
gpr_mu_lock(&resource_lock);
GPR_ASSERT(resources == NULL && n_resources == 0 && n_defined_resources == 0);
@@ -78,16 +70,17 @@ void initialize_resources() {
// Delete a resource given it's ID. Must be called with resource_lock held.
static void delete_resource_locked(size_t rid) {
- GPR_ASSERT(resources[rid] != NULL && resources[rid]->raw_pb != NULL &&
- resources[rid]->name != NULL && n_defined_resources > 0);
+ GPR_ASSERT(resources[rid] != NULL);
gpr_free(resources[rid]->name);
- gpr_free(resources[rid]->raw_pb);
+ gpr_free(resources[rid]->description);
+ gpr_free(resources[rid]->numerators);
+ gpr_free(resources[rid]->denominators);
gpr_free(resources[rid]);
resources[rid] = NULL;
n_defined_resources--;
}
-void shutdown_resources() {
+void shutdown_resources(void) {
gpr_mu_lock(&resource_lock);
for (size_t i = 0; i < n_resources; i++) {
if (resources[i] != NULL) {
@@ -128,8 +121,13 @@ static bool validate_string(pb_istream_t *stream, const pb_field_t *field,
}
break;
case google_census_Resource_description_tag:
- // Description is optional, does not need validating, just skip.
- if (!pb_read(stream, NULL, stream->bytes_left)) {
+ if (stream->bytes_left == 0) {
+ return true;
+ }
+ vresource->description = gpr_malloc(stream->bytes_left + 1);
+ vresource->description[stream->bytes_left] = '\0';
+ if (!pb_read(stream, (uint8_t *)vresource->description,
+ stream->bytes_left)) {
return false;
}
break;
@@ -144,17 +142,47 @@ static bool validate_string(pb_istream_t *stream, const pb_field_t *field,
return true;
}
+// Decode numerators/denominators in a stream. The `count` and `bup`
+// (BasicUnit pointer) are pointers to the approriate fields in a resource
+// struct.
+static bool validate_units_helper(pb_istream_t *stream, int *count,
+ google_census_Resource_BasicUnit **bup) {
+ while (stream->bytes_left) {
+ (*count)++;
+ // Have to allocate a new array of values. Normal case is 0 or 1, so
+ // this should normally not be an issue.
+ google_census_Resource_BasicUnit *new_bup =
+ gpr_malloc((size_t)*count * sizeof(google_census_Resource_BasicUnit));
+ if (*count != 1) {
+ memcpy(new_bup, *bup,
+ (size_t)(*count - 1) * sizeof(google_census_Resource_BasicUnit));
+ gpr_free(*bup);
+ }
+ *bup = new_bup;
+ if (!pb_decode_varint(stream, (uint64_t *)(*bup + *count - 1))) {
+ return false;
+ }
+ }
+ return true;
+}
+
// Validate units field of a Resource proto.
static bool validate_units(pb_istream_t *stream, const pb_field_t *field,
void **arg) {
- if (field->tag == google_census_Resource_MeasurementUnit_numerator_tag) {
- *(bool *)*arg = true; // has_numerator = true.
- }
- while (stream->bytes_left) {
- uint64_t value;
- if (!pb_decode_varint(stream, &value)) {
+ resource *vresource = (resource *)(*arg);
+ switch (field->tag) {
+ case google_census_Resource_MeasurementUnit_numerator_tag:
+ return validate_units_helper(stream, &vresource->n_numerators,
+ &vresource->numerators);
+ break;
+ case google_census_Resource_MeasurementUnit_denominator_tag:
+ return validate_units_helper(stream, &vresource->n_denominators,
+ &vresource->denominators);
+ break;
+ default:
+ gpr_log(GPR_ERROR, "Unknown field type.");
return false;
- }
+ break;
}
return true;
}
@@ -170,10 +198,11 @@ static bool validate_resource_pb(const uint8_t *resource_pb,
vresource.name.funcs.decode = &validate_string;
vresource.name.arg = resources[id];
vresource.description.funcs.decode = &validate_string;
+ vresource.description.arg = resources[id];
vresource.unit.numerator.funcs.decode = &validate_units;
- bool has_numerator = false;
- vresource.unit.numerator.arg = &has_numerator;
+ vresource.unit.numerator.arg = resources[id];
vresource.unit.denominator.funcs.decode = &validate_units;
+ vresource.unit.denominator.arg = resources[id];
pb_istream_t stream =
pb_istream_from_buffer((uint8_t *)resource_pb, resource_pb_size);
@@ -181,17 +210,15 @@ static bool validate_resource_pb(const uint8_t *resource_pb,
return false;
}
// A Resource must have a name, a unit, with at least one numerator.
- return (resources[id]->name != NULL && vresource.has_unit && has_numerator);
+ return (resources[id]->name != NULL && vresource.has_unit &&
+ resources[id]->n_numerators > 0);
}
-int32_t census_define_resource(const uint8_t *resource_pb,
- size_t resource_pb_size) {
+// Allocate a blank resource, and return associated ID. Must be called with
+// resource_lock held.
+size_t allocate_resource(void) {
// use next_id to optimize expected placement of next new resource.
static size_t next_id = 0;
- if (resource_pb == NULL) {
- return -1;
- }
- gpr_mu_lock(&resource_lock);
size_t id = n_resources; // resource ID - initialize to invalid value.
// Expand resources if needed.
if (n_resources == n_defined_resources) {
@@ -212,22 +239,25 @@ int32_t census_define_resource(const uint8_t *resource_pb,
}
GPR_ASSERT(id < n_resources && resources[id] == NULL);
resources[id] = gpr_malloc(sizeof(resource));
- resources[id]->name = NULL;
+ memset(resources[id], 0, sizeof(resource));
+ n_defined_resources++;
+ next_id = (id + 1) % n_resources;
+ return id;
+}
+
+int32_t census_define_resource(const uint8_t *resource_pb,
+ size_t resource_pb_size) {
+ if (resource_pb == NULL) {
+ return -1;
+ }
+ gpr_mu_lock(&resource_lock);
+ size_t id = allocate_resource();
// Validate pb, extract name.
if (!validate_resource_pb(resource_pb, resource_pb_size, id)) {
- if (resources[id]->name != NULL) {
- gpr_free(resources[id]->name);
- }
- gpr_free(resources[id]);
- resources[id] = NULL;
+ delete_resource_locked(id);
gpr_mu_unlock(&resource_lock);
return -1;
}
- next_id = (id + 1) % n_resources;
- // Make copy of raw proto, and return.
- resources[id]->raw_pb = gpr_malloc(resource_pb_size);
- memcpy(resources[id]->raw_pb, resource_pb, resource_pb_size);
- n_defined_resources++;
gpr_mu_unlock(&resource_lock);
return (int32_t)id;
}
@@ -253,3 +283,31 @@ int32_t census_resource_id(const char *name) {
gpr_mu_unlock(&resource_lock);
return -1;
}
+
+int32_t define_resource(const resource *base) {
+ GPR_ASSERT(base != NULL && base->name != NULL && base->n_numerators > 0 &&
+ base->numerators != NULL);
+ gpr_mu_lock(&resource_lock);
+ size_t id = allocate_resource();
+ size_t len = strlen(base->name) + 1;
+ resources[id]->name = gpr_malloc(len);
+ memcpy(resources[id]->name, base->name, len);
+ if (base->description) {
+ len = strlen(base->description);
+ resources[id]->description = gpr_malloc(len);
+ memcpy(resources[id]->description, base->description, len);
+ }
+ resources[id]->prefix = base->prefix;
+ resources[id]->n_numerators = base->n_numerators;
+ len = (size_t)base->n_numerators * sizeof(*base->numerators);
+ resources[id]->numerators = gpr_malloc(len);
+ memcpy(resources[id]->numerators, base->numerators, len);
+ resources[id]->n_denominators = base->n_denominators;
+ if (base->n_denominators != 0) {
+ len = (size_t)base->n_denominators * sizeof(*base->denominators);
+ resources[id]->denominators = gpr_malloc(len);
+ memcpy(resources[id]->denominators, base->denominators, len);
+ }
+ gpr_mu_unlock(&resource_lock);
+ return (int32_t)id;
+}