| /** @file |
| |
| Record utils definitions |
| |
| @section license License |
| |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you 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 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| #include "libts.h" |
| #include "P_RecUtils.h" |
| #include "P_RecCore.h" |
| #include "P_RecTree.h" |
| |
| //------------------------------------------------------------------------- |
| // RecAlloc |
| //------------------------------------------------------------------------- |
| RecRecord* |
| RecAlloc(RecT rec_type, const char *name, RecDataT data_type) |
| { |
| if (g_num_records >= REC_MAX_RECORDS) { |
| Warning("too many stats/configs, please increase REC_MAX_RECORDS or rebuild with --with_max_api_stats=<n>"); |
| return NULL; |
| } |
| |
| int i = ink_atomic_increment(&g_num_records, 1); |
| RecRecord *r = &(g_records[i]); |
| // Note: record should already be memset to 0 from RecCoreInit() |
| r->rec_type = rec_type; |
| r->name = ats_strdup(name); |
| r->order = i; |
| r->data_type = data_type; |
| rec_mutex_init(&(r->lock), NULL); |
| |
| g_records_tree->rec_tree_insert(r->name); |
| |
| return r; |
| } |
| |
| |
| //------------------------------------------------------------------------- |
| // RecDataClear |
| //------------------------------------------------------------------------- |
| void |
| RecDataClear(RecDataT data_type, RecData * data) |
| { |
| if ((data_type == RECD_STRING) && (data->rec_string)) { |
| ats_free(data->rec_string); |
| } |
| memset(data, 0, sizeof(RecData)); |
| } |
| |
| void |
| RecDataSetMax(RecDataT type, RecData * data) |
| { |
| switch (type) { |
| #if defined(STAT_PROCESSOR) |
| case RECD_FX: |
| #endif |
| case RECD_INT: |
| case RECD_COUNTER: |
| data->rec_int = INT64_MAX; // Assumes rec_int is int64_t, which it currently is |
| break; |
| #if defined(STAT_PROCESSOR) |
| case RECD_CONST: |
| #endif |
| case RECD_FLOAT: |
| data->rec_float = FLT_MAX; |
| break; |
| default: |
| Fatal("unsupport type:%d\n", type); |
| } |
| } |
| |
| void |
| RecDataSetMin(RecDataT type, RecData * data) |
| { |
| switch (type) { |
| #if defined(STAT_PROCESSOR) |
| case RECD_FX: |
| #endif |
| case RECD_INT: |
| case RECD_COUNTER: |
| data->rec_int = INT64_MIN; // Assumes rec_int is int64_t, which it currently is |
| break; |
| #if defined(STAT_PROCESSOR) |
| case RECD_CONST: |
| #endif |
| case RECD_FLOAT: |
| data->rec_float = FLT_MIN; |
| break; |
| default: |
| Fatal("unsupport type:%d\n", type); |
| } |
| } |
| |
| //------------------------------------------------------------------------- |
| // RecDataSet |
| //------------------------------------------------------------------------- |
| bool |
| RecDataSet(RecDataT data_type, RecData * data_dst, RecData * data_src) |
| { |
| bool rec_set = false; |
| |
| switch (data_type) { |
| case RECD_STRING: |
| if (data_src->rec_string == NULL) { |
| if (data_dst->rec_string != NULL) { |
| ats_free(data_dst->rec_string); |
| data_dst->rec_string = NULL; |
| rec_set = true; |
| } |
| } else if (((data_dst->rec_string) && (strcmp(data_dst->rec_string, data_src->rec_string) != 0)) || |
| ((data_dst->rec_string == NULL) && (data_src->rec_string != NULL))) { |
| if (data_dst->rec_string) |
| ats_free(data_dst->rec_string); |
| |
| data_dst->rec_string = ats_strdup(data_src->rec_string); |
| rec_set = true; |
| // Chop trailing spaces |
| char *end = data_dst->rec_string + strlen(data_dst->rec_string) - 1; |
| |
| while (end >= data_dst->rec_string && isspace(*end)) |
| end--; |
| *(end + 1) = '\0'; |
| } |
| break; |
| case RECD_INT: |
| if (data_dst->rec_int != data_src->rec_int) { |
| data_dst->rec_int = data_src->rec_int; |
| rec_set = true; |
| } |
| break; |
| case RECD_FLOAT: |
| if (data_dst->rec_float != data_src->rec_float) { |
| data_dst->rec_float = data_src->rec_float; |
| rec_set = true; |
| } |
| break; |
| case RECD_COUNTER: |
| if (data_dst->rec_counter != data_src->rec_counter) { |
| data_dst->rec_counter = data_src->rec_counter; |
| rec_set = true; |
| } |
| break; |
| default: |
| ink_assert(!"Wrong RECD type!"); |
| } |
| return rec_set; |
| |
| } |
| |
| int |
| RecDataCmp(RecDataT type, RecData left, RecData right) |
| { |
| switch (type) { |
| #if defined(STAT_PROCESSOR) |
| case RECD_FX: |
| #endif |
| case RECD_INT: |
| case RECD_COUNTER: |
| if (left.rec_int > right.rec_int) |
| return 1; |
| else if (left.rec_int == right.rec_int) |
| return 0; |
| else |
| return -1; |
| #if defined(STAT_PROCESSOR) |
| case RECD_CONST: |
| #endif |
| case RECD_FLOAT: |
| if (left.rec_float > right.rec_float) |
| return 1; |
| else if (left.rec_float == right.rec_float) |
| return 0; |
| else |
| return -1; |
| default: |
| Fatal("unsupport type:%d\n", type); |
| return 0; |
| } |
| } |
| |
| RecData |
| RecDataAdd(RecDataT type, RecData left, RecData right) |
| { |
| RecData val; |
| memset(&val, 0, sizeof(val)); |
| |
| switch (type) { |
| #if defined(STAT_PROCESSOR) |
| case RECD_FX: |
| #endif |
| case RECD_INT: |
| case RECD_COUNTER: |
| val.rec_int = left.rec_int + right.rec_int; |
| break; |
| #if defined(STAT_PROCESSOR) |
| case RECD_CONST: |
| #endif |
| case RECD_FLOAT: |
| val.rec_float = left.rec_float + right.rec_float; |
| break; |
| default: |
| Fatal("unsupported type:%d\n", type); |
| break; |
| } |
| return val; |
| } |
| |
| RecData |
| RecDataSub(RecDataT type, RecData left, RecData right) |
| { |
| RecData val; |
| memset(&val, 0, sizeof(val)); |
| |
| switch (type) { |
| #if defined(STAT_PROCESSOR) |
| case RECD_FX: |
| #endif |
| case RECD_INT: |
| case RECD_COUNTER: |
| val.rec_int = left.rec_int - right.rec_int; |
| break; |
| #if defined(STAT_PROCESSOR) |
| case RECD_CONST: |
| #endif |
| case RECD_FLOAT: |
| val.rec_float = left.rec_float - right.rec_float; |
| break; |
| default: |
| Fatal("unsupported type:%d\n", type); |
| break; |
| } |
| return val; |
| } |
| |
| RecData |
| RecDataMul(RecDataT type, RecData left, RecData right) |
| { |
| RecData val; |
| memset(&val, 0, sizeof(val)); |
| |
| switch (type) { |
| #if defined(STAT_PROCESSOR) |
| case RECD_FX: |
| #endif |
| case RECD_INT: |
| case RECD_COUNTER: |
| val.rec_int = left.rec_int * right.rec_int; |
| break; |
| #if defined(STAT_PROCESSOR) |
| case RECD_CONST: |
| #endif |
| case RECD_FLOAT: |
| val.rec_float = left.rec_float * right.rec_float; |
| break; |
| default: |
| Fatal("unsupported type:%d\n", type); |
| break; |
| } |
| return val; |
| } |
| |
| RecData |
| RecDataDiv(RecDataT type, RecData left, RecData right) |
| { |
| RecData val; |
| memset(&val, 0, sizeof(val)); |
| |
| switch (type) { |
| #if defined(STAT_PROCESSOR) |
| case RECD_FX: |
| #endif |
| case RECD_INT: |
| case RECD_COUNTER: |
| val.rec_int = left.rec_int / right.rec_int; |
| break; |
| #if defined(STAT_PROCESSOR) |
| case RECD_CONST: |
| #endif |
| case RECD_FLOAT: |
| val.rec_float = left.rec_float / right.rec_float; |
| break; |
| default: |
| Fatal("unsupported type:%d\n", type); |
| break; |
| } |
| return val; |
| } |
| |
| //------------------------------------------------------------------------- |
| // RecDataSetFromInk64 |
| //------------------------------------------------------------------------- |
| bool |
| RecDataSetFromInk64(RecDataT data_type, RecData * data_dst, int64_t data_int64) |
| { |
| switch (data_type) { |
| #if defined(STAT_PROCESSOR) |
| case RECD_FX: |
| #endif |
| case RECD_INT: |
| data_dst->rec_int = data_int64; |
| break; |
| #if defined(STAT_PROCESSOR) |
| case RECD_CONST: |
| #endif |
| case RECD_FLOAT: |
| data_dst->rec_float = (float) (data_int64); |
| break; |
| case RECD_STRING: |
| { |
| char buf[32 + 1]; |
| |
| ats_free(data_dst->rec_string); |
| snprintf(buf, 32, "%" PRId64 "", data_int64); |
| data_dst->rec_string = ats_strdup(buf); |
| break; |
| } |
| case RECD_COUNTER: |
| data_dst->rec_counter = data_int64; |
| break; |
| default: |
| ink_assert(!"Unexpected RecD type"); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| |
| //------------------------------------------------------------------------- |
| // RecDataSetFromFloat |
| //------------------------------------------------------------------------- |
| bool |
| RecDataSetFromFloat(RecDataT data_type, RecData * data_dst, float data_float) |
| { |
| switch (data_type) { |
| #if defined(STAT_PROCESSOR) |
| case RECD_FX: |
| #endif |
| case RECD_INT: |
| data_dst->rec_int = (RecInt) data_float; |
| break; |
| #if defined(STAT_PROCESSOR) |
| case RECD_CONST: |
| #endif |
| case RECD_FLOAT: |
| data_dst->rec_float = (float) (data_float); |
| break; |
| case RECD_STRING: |
| { |
| char buf[32 + 1]; |
| |
| ats_free(data_dst->rec_string); |
| snprintf(buf, 32, "%f", data_float); |
| data_dst->rec_string = ats_strdup(buf); |
| break; |
| } |
| case RECD_COUNTER: |
| data_dst->rec_counter = (RecCounter) data_float; |
| break; |
| default: |
| ink_assert(!"Unexpected RecD type"); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| |
| //------------------------------------------------------------------------- |
| // RecDataSetFromString |
| //------------------------------------------------------------------------- |
| bool |
| RecDataSetFromString(RecDataT data_type, RecData * data_dst, const char *data_string) |
| { |
| bool rec_set; |
| RecData data_src; |
| |
| switch (data_type) { |
| #if defined(STAT_PROCESSOR) |
| case RECD_FX: |
| #endif |
| case RECD_INT: |
| data_src.rec_int = ink_atoi64(data_string); |
| break; |
| #if defined(STAT_PROCESSOR) |
| case RECD_CONST: |
| #endif |
| case RECD_FLOAT: |
| data_src.rec_float = atof(data_string); |
| break; |
| case RECD_STRING: |
| if (strcmp((data_string), "NULL") == 0) { |
| data_src.rec_string = NULL; |
| } else { |
| // It's OK to cast away the const here, because RecDataSet will copy the string. |
| data_src.rec_string = (char *)data_string; |
| } |
| break; |
| case RECD_COUNTER: |
| data_src.rec_counter = ink_atoi64(data_string); |
| break; |
| default: |
| ink_assert(!"Unexpected RecD type"); |
| return false; |
| } |
| rec_set = RecDataSet(data_type, data_dst, &data_src); |
| |
| return rec_set; |
| } |
| |