Permalink
Browse files

crash when different vm threads try to update same metric fixed

  • Loading branch information...
1 parent d21a65b commit 258dbc0f62a2a9203bdc8f5f5830c0f3ab9493f2 @petrkozorezov committed Mar 1, 2012
Showing with 34 additions and 2 deletions.
  1. +34 −2 c_src/basho_metrics_nifs.cpp
@@ -29,6 +29,9 @@
#include <cmath>
#include <vector>
#include <cstring>
+extern "C" {
+ #include <pthread.h>
+}
static ErlNifResourceType* histogram_RESOURCE;
static ErlNifResourceType* meter_RESOURCE;
@@ -38,12 +41,14 @@ static const unsigned long DEFAULT_METER_TICK_INTERVAL = 1000;
struct meter_handle
{
+ pthread_mutex_t m;
unsigned long tick_interval;
meter<> *p;
};
struct histogram_handle
{
+ pthread_mutex_t m;
std::size_t size;
histogram<> *p;
};
@@ -148,6 +153,7 @@ ERL_NIF_TERM histogram_new(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
if (enif_is_list(env, argv[0]))
{
memset(handle, '\0', sizeof(histogram_handle));
+ pthread_mutex_init(&(handle->m), NULL);
handle->size = DEFAULT_RESERVOIR_SIZE;
fold(env, argv[0], parse_histogram_option, *handle);
handle->p = new histogram<>(handle->size);
@@ -166,7 +172,9 @@ ERL_NIF_TERM histogram_clear(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
histogram_handle* handle;
if (enif_get_resource(env,argv[0],histogram_RESOURCE,(void**)&handle))
{
+ pthread_mutex_lock(&(handle->m));
handle->p->clear();
+ pthread_mutex_unlock(&(handle->m));
return ATOM_OK;
}
else
@@ -182,7 +190,9 @@ ERL_NIF_TERM histogram_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
if (enif_get_resource(env,argv[0],histogram_RESOURCE,(void**)&handle) &&
enif_get_ulong(env, argv[1], &sample))
{
+ pthread_mutex_lock(&(handle->m));
handle->p->update(sample);
+ pthread_mutex_unlock(&(handle->m));
return ATOM_OK;
}
else
@@ -196,12 +206,16 @@ ERL_NIF_TERM histogram_stats(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
histogram_handle* handle;
if (enif_get_resource(env,argv[0],histogram_RESOURCE,(void**)&handle))
{
+ pthread_mutex_lock(&(handle->m));
+
std::vector<double> percentiles;
percentiles.push_back(0.500);
percentiles.push_back(0.950);
percentiles.push_back(0.990);
std::vector<double> scores(handle->p->percentiles(percentiles));
- return enif_make_list8(env,
+
+ ERL_NIF_TERM result =
+ enif_make_list8(env,
STAT_TUPLE(ATOM_MIN, handle->p->min()),
STAT_TUPLE(ATOM_MAX, handle->p->max()),
STAT_TUPLE(ATOM_MEAN, handle->p->mean()),
@@ -211,6 +225,8 @@ ERL_NIF_TERM histogram_stats(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
STAT_TUPLE(ATOM_P95, scores[1]),
STAT_TUPLE(ATOM_P99, scores[2]));
+ pthread_mutex_unlock(&(handle->m));
+ return result;
}
else
return enif_make_badarg(env);
@@ -224,6 +240,7 @@ ERL_NIF_TERM meter_new(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
if (enif_is_list(env, argv[0]))
{
memset(handle, '\0', sizeof(meter_handle));
+ pthread_mutex_init(&(handle->m), NULL);
handle->tick_interval = DEFAULT_METER_TICK_INTERVAL;
fold(env, argv[0], parse_meter_option, *handle);
handle->p = new meter<>(handle->tick_interval);
@@ -242,7 +259,9 @@ ERL_NIF_TERM meter_tick(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
meter_handle *handle;
if (enif_get_resource(env,argv[0],meter_RESOURCE,(void**)&handle))
{
+ pthread_mutex_lock(&(handle->m));
handle->p->tick();
+ pthread_mutex_unlock(&(handle->m));
return ATOM_OK;
}
else
@@ -258,7 +277,9 @@ ERL_NIF_TERM meter_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
if (enif_get_resource(env,argv[0],meter_RESOURCE,(void**)&handle) &&
enif_get_ulong(env, argv[1], &sample))
{
+ pthread_mutex_lock(&(handle->m));
handle->p->mark(sample);
+ pthread_mutex_unlock(&(handle->m));
return ATOM_OK;
}
else
@@ -272,13 +293,18 @@ ERL_NIF_TERM meter_stats(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
meter_handle* handle;
if (enif_get_resource(env,argv[0],meter_RESOURCE,(void**)&handle))
{
- return enif_make_list4(env,
+ pthread_mutex_lock(&(handle->m));
+
+ ERL_NIF_TERM result =
+ enif_make_list4(env,
enif_make_tuple2(env,ATOM_COUNT,
enif_make_ulong(env, handle->p->count())),
enif_make_tuple2(env,ATOM_ONE,
enif_make_double(env,handle->p->one())),
enif_make_tuple2(env,ATOM_FIVE,enif_make_double(env, handle->p->five())),
enif_make_tuple2(env,ATOM_FIFTEEN,enif_make_double(env, handle->p->fifteen())));
+ pthread_mutex_unlock(&(handle->m));
+ return result;
}
else
return enif_make_badarg(env);
@@ -287,12 +313,18 @@ ERL_NIF_TERM meter_stats(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
static void histogram_resource_cleanup(ErlNifEnv* env, void* arg)
{
histogram_handle* handle = (histogram_handle*)arg;
+
+ pthread_mutex_destroy(&(handle->m));
+
delete handle->p;
}
static void meter_resource_cleanup(ErlNifEnv* env, void* arg)
{
meter_handle* handle = (meter_handle*)arg;
+
+ pthread_mutex_destroy(&(handle->m));
+
delete handle->p;
}

0 comments on commit 258dbc0

Please sign in to comment.