Beispiel #1
0
/**
 * Callback function to use with INI-H.
 * @arg user Opaque user value. We use the statsite_config pointer
 * @arg section The INI seciton
 * @arg name The config name
 * @arg value The config value
 * @return 1 on success.
 */
static int config_callback(void* user, const char* section, const char* name, const char* value) {
    // Specially handle histogram sections
    if (strncasecmp("histogram", section, 9) == 0) {
        return histogram_callback(user, section, name, value);
    }

    // Ignore any non-statsite sections
    if (strcasecmp("statsite", section) != 0) {
        return 0;
    }

    // Cast the user handle
    statsite_config *config = (statsite_config*)user;

    // Switch on the config
    #define NAME_MATCH(param) (strcasecmp(param, name) == 0)

    // Handle the int cases
    if (NAME_MATCH("port")) {
        return value_to_int(value, &config->tcp_port);
    } else if (NAME_MATCH("tcp_port")) {
        return value_to_int(value, &config->tcp_port);
    } else if (NAME_MATCH("udp_port")) {
        return value_to_int(value, &config->udp_port);
    } else if (NAME_MATCH("flush_interval")) {
         return value_to_int(value, &config->flush_interval);
    } else if (NAME_MATCH("daemonize")) {
        return value_to_bool(value, &config->daemonize);
    } else if (NAME_MATCH("binary_stream")) {
        return value_to_bool(value, &config->binary_stream);

    // Handle the double cases
    } else if (NAME_MATCH("timer_eps")) {
        return value_to_double(value, &config->timer_eps);
    } else if (NAME_MATCH("set_eps")) {
        return value_to_double(value, &config->set_eps);

    // Copy the string values
    } else if (NAME_MATCH("log_level")) {
        config->log_level = strdup(value);
    } else if (NAME_MATCH("stream_cmd")) {
        config->stream_cmd = strdup(value);
    } else if (NAME_MATCH("pid_file")) {
        config->pid_file = strdup(value);
    } else if (NAME_MATCH("input_counter")) {
        config->input_counter = strdup(value);
    } else if (NAME_MATCH("bind_address")) {
        config->bind_address = strdup(value);

    // Unknown parameter?
    } else {
        // Log it, but ignore
        syslog(LOG_NOTICE, "Unrecognized config parameter: %s", value);
    }

    // Success
    return 1;
}
Beispiel #2
0
kj_internal kj_bool vm_comp_lte(value_t const *lhs, value_t const *rhs)
{
	switch (lhs->type) {
		case KJ_TYPE_NIL:  return true;
		case KJ_TYPE_BOOL: return lhs->boolean <= value_to_int(rhs);
		case KJ_TYPE_INT:  return lhs->integer <= value_to_int(rhs);
		case KJ_TYPE_REAL: return lhs->real <= value_to_real(rhs);
		case KJ_TYPE_STRING: return rhs->type == KJ_TYPE_STRING &&
			(lhs->string->length < rhs->string->length ||
			(lhs->string->length == rhs->string->length &&
				memcmp(lhs->string->data, rhs->string->data, lhs->string->length) <= 0));
		case KJ_TYPE_TABLE:  return rhs->type == KJ_TYPE_TABLE && lhs->table <= rhs->table;
		default: assert(!"implement me");
	}
	return false;
}
Beispiel #3
0
kj_internal void vm_op_mul(vm_t *vm, value_t *dest, value_t const *lhs, value_t const *rhs)
{
	switch (lhs->type)
	{
		case KJ_TYPE_STRING:
		{
			if (rhs->type != KJ_TYPE_INT && rhs->type != KJ_TYPE_REAL) goto error;

			kj_integer repetitions = value_to_int(rhs);
			if (repetitions < 0) {
				vm_throw(vm, "rhs value of string by integer multiplication must be non negative, it is " KJ_INTEGER_PRF ".", repetitions);
			}

			uint dest_length = (uint)(lhs->string->length * repetitions);

			value_t temp = { 0 };
			value_new_string(&temp, vm->allocator, dest_length);

			/* copy lhs into dest 'rhs' times */
			for (kj_integer i = 0; i < repetitions; ++i) {
				memcpy(temp.string->data + lhs->string->length * i, lhs->string->data, lhs->string->length);
			}

			temp.string->data[dest_length] = '\0';

			value_destroy(dest, vm->allocator);
			*dest = temp;
			break;
		}

		DEFAULT_BINOP_CASES(*)
	}
}
Beispiel #4
0
static Value
_lib_char_code_at(VMState *vm, Value value)
{
    Hash *args = value_to_ptr(value);
    CString *string = value_to_string(hash_find(args, 1));
    int index = value_to_int(hash_find(args, 2));

    if (index < 0 || index >= string->length) {
        error_f("Out of range when get char_at(%.*s, %d)", string->length, string->content, index);
        return value_undefined();
    }

    return value_from_int(string->content[index]);
}
Beispiel #5
0
static Value
_lib_to_string(VMState *vm, Value value)
{
    Hash *args = value_to_ptr(value);
    Value query_val = hash_find(args, 1);

    if (value_is_int(query_val)) {
        char buffer[30];
        sprintf(buffer, "%d", value_to_int(query_val));
        return cvm_get_cstring_value(vm, buffer);
    }
    else {
        return _lib_typeof(vm, value);
    }
}
Beispiel #6
0
static Value
_lib_char_at(VMState *vm, Value value)
{
    Hash *args = value_to_ptr(value);
    CString *string = value_to_string(hash_find(args, 1));
    int index = value_to_int(hash_find(args, 2));

    if (index < 0 || index >= string->length) {
        error_f("Out of range when get char_at(%.*s, %d)", string->length, string->content, index);
        return value_undefined();
    }

    char buffer[2];
    buffer[0] = string->content[index];
    buffer[1] = 0;

    return cvm_get_cstring_value(vm, buffer);
}
Beispiel #7
0
/*
 * This function implements the "target = object[key]" syntax in the language.
 * The semantics depend on the type of target, but the idea is that the sub-element with specified
 * @key in @object will be put in in @target
 */
kj_internal void vm_get_property(vm_t *vm, value_t *target, value_t const *object, value_t const *key)
{
	switch (object->type)
	{
		case KJ_TYPE_TABLE:
			value_set(target, vm->allocator, table_get(&object->table->table, key));
			break;

		case KJ_TYPE_STRING:
			// #todo add short string optimization
			value_new_string(target, vm->allocator, 1);
			target->string->data[0] = object->string->data[value_to_int(key)];
			target->string->data[1] = '\0';
			break;

		default:
			vm_throw(vm, "invalid get operation performed on value of type %s.", VALUE_TYPE_STRING[object->type]);
	}
}
Beispiel #8
0
static Value
_lib_print(VMState *vm, Value value)
{
    Hash *args = value_to_ptr(value);

    for (uintptr_t i = 1; i < hash_size(args); ++i) {
        Value val = hash_find(args, i);

        if (value_is_int(val)) {
            printf("%d", value_to_int(val));
        }
        else {
            CString *string = value_to_string(val);
            printf("%.*s", string->length, string->content);
        }
    }

    return value_undefined();
}
Beispiel #9
0
/*-----------------------------------------------------------------------------------------------*/
kj_internal kj_bool vm_comp_eq(value_t const *lhs, value_t const *rhs)
{
	switch (lhs->type) {
		case KJ_TYPE_NIL:  return rhs->type == KJ_TYPE_NIL;
		case KJ_TYPE_BOOL: return rhs->type == KJ_TYPE_BOOL && lhs->boolean == rhs->boolean;
		case KJ_TYPE_INT:  return rhs->type == KJ_TYPE_REAL ? lhs->integer == rhs->real : lhs->integer == value_to_int(rhs);
		case KJ_TYPE_REAL: return lhs->real == value_to_real(rhs);
		case KJ_TYPE_STRING: return rhs->type == KJ_TYPE_STRING &&
			lhs->string->length == rhs->string->length &&
			memcmp(lhs->string->data, rhs->string->data, lhs->string->length);
		case KJ_TYPE_TABLE:  return rhs->type == KJ_TYPE_TABLE && lhs->table == rhs->table;
		default: 
			assert(!"implement me");
	}
	return false;
}
Beispiel #10
0
/**
 * Callback function to use with INI-H.
 * @arg user Opaque user value. We use the statsite_config pointer
 * @arg section The INI seciton
 * @arg name The config name
 * @arg value The config value
 * @return 1 on success.
 */
static int config_callback(void* user, const char* section, const char* name, const char* value) {
    // Specially handle histogram sections
    if (strncasecmp("histogram", section, 9) == 0) {
        return histogram_callback(user, section, name, value);
    }

    if (strncasecmp("sink", section, 4) == 0) {
        return sink_callback(user, section, name, value);
    }

    // Ignore any non-statsite sections
    if (strcasecmp("statsite", section) != 0) {
        syslog(LOG_NOTICE, "Unknown values in section ignored: %s", section);
        return 0;
    }

    // Cast the user handle
    statsite_config *config = (statsite_config*)user;

    // Handle the int cases
    if (NAME_MATCH("port")) {
        return value_to_int(value, &config->tcp_port);
    } else if (NAME_MATCH("tcp_port")) {
        return value_to_int(value, &config->tcp_port);
    } else if (NAME_MATCH("udp_port")) {
        return value_to_int(value, &config->udp_port);
    } else if (NAME_MATCH("flush_interval")) {
         return value_to_int(value, &config->flush_interval);
    } else if (NAME_MATCH("parse_stdin")) {
        return value_to_bool(value, &config->parse_stdin);
    } else if (NAME_MATCH("daemonize")) {
        return value_to_bool(value, &config->daemonize);
    } else if (NAME_MATCH("use_type_prefix")) {
        return value_to_bool(value, &config->use_type_prefix);
    } else if (NAME_MATCH("extended_counters")) {
        return value_to_bool(value, &config->extended_counters);
    } else if (NAME_MATCH("prefix_binary_stream")) {
        return value_to_bool(value, &config->prefix_binary_stream);

    // Handle the double cases
    } else if (NAME_MATCH("timer_eps")) {
        return value_to_double(value, &config->timer_eps);
    } else if (NAME_MATCH("set_eps")) {
        return value_to_double(value, &config->set_eps);

    // Handle quantiles as a comma-separated list of doubles
    } else if (NAME_MATCH("quantiles")) {
        return value_to_list_of_doubles(value, &config->quantiles, &config->num_quantiles);

    // Copy the string values
    } else if (NAME_MATCH("log_level")) {
        config->log_level = strdup(value);
    } else if (NAME_MATCH("log_facility")) {
        config->log_facility = strdup(value);
    } else if (NAME_MATCH("pid_file")) {
        config->pid_file = strdup(value);
    } else if (NAME_MATCH("input_counter")) {
        config->input_counter = strdup(value);
    } else if (NAME_MATCH("bind_address")) {
        config->bind_address = strdup(value);
    } else if (NAME_MATCH("global_prefix")) {
        config->global_prefix = strdup(value);
    } else if (NAME_MATCH("counts_prefix")) {
        config->prefixes[COUNTER] = strdup(value);
    } else if (NAME_MATCH("gauges_prefix")) {
        config->prefixes[GAUGE] = strdup(value);
    } else if (NAME_MATCH("timers_prefix")) {
        config->prefixes[TIMER] = strdup(value);
    } else if (NAME_MATCH("sets_prefix")) {
        config->prefixes[SET] = strdup(value);
    } else if (NAME_MATCH("kv_prefix")) {
        config->prefixes[KEY_VAL] = strdup(value);

    // Copy the multi-case variables
    } else if (NAME_MATCH("log_facility")) {
        return name_to_facility(value, &config->syslog_log_facility);

    // Unknown parameter?
    } else {
        // Log it, but ignore
        syslog(LOG_NOTICE, "Unrecognized config parameter: %s", name);
    }

    // Success
    return 1;
}
Beispiel #11
0
/**
 * Callback function to use with INIH for parsing sink configurations.
 * The sink type is currently encoded into the section name to
 * simplify instantiating the correct configuration type.
 */
static int sink_callback(void* user, const char* section, const char* name, const char* value) {

    statsite_config *all_config = (statsite_config*)user;

    /* The sink section does not match - lets commit since we're on to a new one now */
    if (sink_in_progress && strcasecmp(sink_section, section)) {
        sink_commit(all_config);
    }

    /* Nothing in progress? Create it! */
    if (!sink_in_progress) {
        if (!sink_section)
            sink_section = strdup(section);

        char* section_to_tokenize = strdup(section);
        char* tok = NULL;
        char* header = strtok_r(section_to_tokenize, "_", &tok);
        char* type = strtok_r(NULL, "_", &tok);
        char* name = strtok_r(NULL, "_", &tok);

        if (header == NULL || type == NULL || name == NULL) {
            free(section_to_tokenize);
            syslog(LOG_WARNING, "Sink section %s is not of the form \"sink_[type]_[name]\"", section);
            return 0;
        }
        /* Match various sink types to find their type */
        if (strcasecmp(type, "stream") == 0) {
            sink_config_stream* config = calloc(1, sizeof(sink_config_stream));
            sink_in_progress = (sink_config*)config;
            config->super.type = SINK_TYPE_STREAM;
            config->super.name = strdup(name);
            config->stream_cmd = DEFAULT_SINK.stream_cmd;
        } else if (strcasecmp(type, "http") == 0) {
            sink_config_http* config = malloc(sizeof(sink_config_http));

            memcpy(config, &DEFAULT_HTTP_SINK, sizeof(sink_config_http));
            sink_in_progress = (sink_config*)config;
            config->super.name = strdup(name);
        } else {
            free(section_to_tokenize);
            /* Unknown sink type - abort! */
            syslog(LOG_WARNING, "Unknown sink type: %s for sink: %s", type, name);
            return 0;
        }
        free(section_to_tokenize);
    }

    switch(sink_in_progress->type) {
    case SINK_TYPE_STREAM:
    {
        sink_config_stream* config = (sink_config_stream*)sink_in_progress;
        if (NAME_MATCH("binary")) {
            return value_to_bool(value, &config->binary_stream);
        } else if (NAME_MATCH("command")) {
            config->stream_cmd = strdup(value);
        } else {
            syslog(LOG_NOTICE, "Unrecognized stream sink parameter: %s", name);
            return 0;
        }
        break;
    }
    case SINK_TYPE_HTTP:
    {
        sink_config_http* config = (sink_config_http*)sink_in_progress;
        if (NAME_MATCH("url")) {
            config->post_url = strdup(value);
        } else if (NAME_MATCH("metrics_name")) {
            config->metrics_name = strdup(value);
        } else if (NAME_MATCH("timestamp_name")) {
            config->timestamp_name = strdup(value);
        } else if (NAME_MATCH("timestamp_format")) {
            config->timestamp_format = strdup(value);
        } else if (NAME_MATCH("ciphers")) {
            config->ciphers = strdup(value);
        } else if (NAME_MATCH("oauth_key")) {
            config->oauth_key = strdup(value);
        } else if (NAME_MATCH("oauth_secret")) {
            config->oauth_secret = strdup(value);
        } else if (NAME_MATCH("oauth_token_url")) {
            config->oauth_token_url = strdup(value);
        } else if (NAME_MATCH("max_buffer_size")) {
            value_to_int(value, &config->max_buffer_size);
        } else if (NAME_MATCH("send_backoff_ms")) {
            value_to_int(value, &config->send_backoff_ms);
        } else {
            /* Attempt to locate keys
             * of the form param_PNAME */
            char* param_tok = strdup(name);
            char* tok = NULL;
            char* header = strtok_r(param_tok, "_", &tok);
            char* param = strtok_r(NULL, "_", &tok);
            if (header == NULL || param == NULL || strcasecmp("param", header) != 0) {
                syslog(LOG_NOTICE, "Unrecognized http sink parameters: %s: %s", name, header);
                free(param_tok);
                return 0;
            }
            kv_config* last_kv = config->params;
            config->params = calloc(1, sizeof(kv_config));
            config->params->k = strdup(param);
            config->params->v = strdup(value);
            config->params->next = last_kv;
            free(param_tok);
        }
        break;
    }
    default:
        syslog(LOG_WARNING, "Grevious state problem");
        return 0;
    }

    return 1;
}
Beispiel #12
0
/**
 * Callback function to use with INI-H.
 * @arg user Opaque user value. We use the hlld_config pointer
 * @arg section The INI seciton
 * @arg name The config name
 * @arg value The config value
 * @return 1 on success.
 */
static int config_callback(void* user, const char* section, const char* name, const char* value) {
    // Ignore any non-hlld sections
    if (strcasecmp("hlld", section) != 0) {
        return 0;
    }

    // Cast the user handle
    hlld_config *config = (hlld_config*)user;

    // Switch on the config
#define NAME_MATCH(param) (strcasecmp(param, name) == 0)

    // Handle the int cases
    if (NAME_MATCH("port")) {
        return value_to_int(value, &config->tcp_port);
    } else if (NAME_MATCH("tcp_port")) {
        return value_to_int(value, &config->tcp_port);
    } else if (NAME_MATCH("udp_port")) {
        return value_to_int(value, &config->udp_port);
    } else if (NAME_MATCH("flush_interval")) {
        return value_to_int(value, &config->flush_interval);
    } else if (NAME_MATCH("cold_interval")) {
        return value_to_int(value, &config->cold_interval);
    } else if (NAME_MATCH("in_memory")) {
        return value_to_int(value, &config->in_memory);
    } else if (NAME_MATCH("use_mmap")) {
        return value_to_int(value, &config->use_mmap);
    } else if (NAME_MATCH("workers")) {
        return value_to_int(value, &config->worker_threads);
    } else if (NAME_MATCH("default_precision")) {
        int res = value_to_int(value, &config->default_precision);
        // Compute expected error given precision
        config->default_eps = hll_error_for_precision(config->default_precision);
        return res;

        // Handle the double cases
    } else if (NAME_MATCH("default_eps")) {
        int res = value_to_double(value, &config->default_eps);
        // Compute required precision given error
        config->default_precision = hll_precision_for_error(config->default_eps);

        // Compute error given precision. This is kinda strange but it is done
        // since its not possible to hit all epsilons perfectly, but we try to get
        // the eps provided to be the upper bound. This value is the actual eps.
        config->default_eps = hll_error_for_precision(config->default_precision);
        return res;

        // Copy the string values
    } else if (NAME_MATCH("data_dir")) {
        config->data_dir = strdup(value);
    } else if (NAME_MATCH("log_level")) {
        config->log_level = strdup(value);

        // Unknown parameter?
    } else {
        // Log it, but ignore
        syslog(LOG_NOTICE, "Unrecognized config parameter: %s", value);
    }

    // Success
    return 1;
}
Beispiel #13
0
    X(bool, "Booleans can be stored inline") \
    X(ptr, "Boxed values should be heap-allocated and a pointer stored") \
    X(value_type, "Value type should be not depend on whether or not the value is boxed") \
    X(gray_bit, "Boxed values should maintain a gray bit") \
    X(hash, "Value hashes should be well-distributed") \
    X(hash_tuple, "Hashes from equal tuples should be equal") \
    X(equal, "Only equal values should be equal")

TEST(double)
    value_t x = value_from_double(42.101010);
    PT_ASSERT_EQ(value_to_double(x), 42.101010);
END(double)

TEST(fixnum)
    value_t x = value_from_int(322);
    PT_ASSERT_EQ(value_to_int(x), 322);
END(fixnum)

TEST(bool)
    value_t x = value_true();
    PT_ASSERT(value_to_bool(x));
    x = value_false();
    PT_ASSERT(!value_to_bool(x));
END(bool)

TEST(ptr)
    struct arena_handle *a = arena_new((yu_allocator *)&mctx);
    struct boxed_value *v = arena_alloc_val(a);
    value_t x = value_from_ptr(&v);
    PT_ASSERT_EQ(value_get_ptr(x), v);
    PT_ASSERT_EQ(boxed_value_owner(v), a);