diff --git a/doc/libpmemobj/pmemobj_ctl_get.3.md b/doc/libpmemobj/pmemobj_ctl_get.3.md
index 00a599883ff..58f533df013 100644
--- a/doc/libpmemobj/pmemobj_ctl_get.3.md
+++ b/doc/libpmemobj/pmemobj_ctl_get.3.md
@@ -320,6 +320,18 @@ The required class identifier will be stored in the `class_id` field of the
This function returns 0 if the allocation class has been successfully created,
-1 otherwise.
+stats.enabled | rw | - | int | int | - | boolean
+
+Enables or disables runtime collection of statistics. The statistics are never
+altered after enabling.
+
+Always returns 0.
+
+stats.heap.allocated_curr | r- | - | int | - | - | -
+
+Returns the number of bytes currently allocated in the heap. If statistics were
+disabled at any time in the lifetime of the heap, this value might be
+inaccurate.
# CTL EXTERNAL CONFIGURATION #
diff --git a/src/benchmarks/pmembench.vcxproj b/src/benchmarks/pmembench.vcxproj
index 038a6d9dd45..c1250db8169 100644
--- a/src/benchmarks/pmembench.vcxproj
+++ b/src/benchmarks/pmembench.vcxproj
@@ -115,6 +115,10 @@
CompileAsC
CompileAsC
+
+ CompileAsC
+ CompileAsC
+
CompileAsC
CompileAsC
diff --git a/src/libpmemobj/Makefile b/src/libpmemobj/Makefile
index 84c6de8d514..26c4e083425 100644
--- a/src/libpmemobj/Makefile
+++ b/src/libpmemobj/Makefile
@@ -61,7 +61,8 @@ SOURCE +=\
redo.c\
ringbuf.c\
sync.c\
- tx.c
+ tx.c\
+ stats.c
include ../Makefile.inc
diff --git a/src/libpmemobj/heap.c b/src/libpmemobj/heap.c
index c5d8be25d21..cb289c3e193 100644
--- a/src/libpmemobj/heap.c
+++ b/src/libpmemobj/heap.c
@@ -1170,7 +1170,8 @@ heap_buckets_init(struct palloc_heap *heap)
*/
int
heap_boot(struct palloc_heap *heap, void *heap_start, uint64_t heap_size,
- uint64_t run_id, void *base, struct pmem_ops *p_ops)
+ uint64_t run_id, void *base, struct pmem_ops *p_ops,
+ struct stats *stats)
{
struct heap_rt *h = Malloc(sizeof(*h));
int err;
@@ -1207,6 +1208,7 @@ heap_boot(struct palloc_heap *heap, void *heap_start, uint64_t heap_size,
heap->rt = h;
heap->size = heap_size;
heap->base = base;
+ heap->stats = stats;
VALGRIND_DO_CREATE_MEMPOOL(heap->layout, 0, 0);
for (unsigned i = 0; i < h->narenas; ++i)
diff --git a/src/libpmemobj/heap.h b/src/libpmemobj/heap.h
index 8d36feb5f35..5d8557e9fb8 100644
--- a/src/libpmemobj/heap.h
+++ b/src/libpmemobj/heap.h
@@ -56,7 +56,8 @@
#define BIT_IS_CLR(a, i) (!((a) & (1ULL << (i))))
int heap_boot(struct palloc_heap *heap, void *heap_start, uint64_t heap_size,
- uint64_t run_id, void *base, struct pmem_ops *p_ops);
+ uint64_t run_id, void *base, struct pmem_ops *p_ops,
+ struct stats *stats);
int heap_init(void *heap_start, uint64_t heap_size, struct pmem_ops *p_ops);
void heap_cleanup(struct palloc_heap *heap);
int heap_check(void *heap_start, uint64_t heap_size);
diff --git a/src/libpmemobj/libpmemobj.vcxproj b/src/libpmemobj/libpmemobj.vcxproj
index c1cc081bc23..c1fea0d3b61 100644
--- a/src/libpmemobj/libpmemobj.vcxproj
+++ b/src/libpmemobj/libpmemobj.vcxproj
@@ -48,6 +48,7 @@
+
@@ -104,6 +105,7 @@
+
diff --git a/src/libpmemobj/libpmemobj.vcxproj.filters b/src/libpmemobj/libpmemobj.vcxproj.filters
index 0c52df76ce3..bc953d412a7 100644
--- a/src/libpmemobj/libpmemobj.vcxproj.filters
+++ b/src/libpmemobj/libpmemobj.vcxproj.filters
@@ -112,6 +112,9 @@
Source Files
+
+ Source Files
+
Source Files
@@ -264,6 +267,9 @@
Header Files
+
+ Header Files
+
Header Files
diff --git a/src/libpmemobj/obj.c b/src/libpmemobj/obj.c
index d6dd207ecd3..411b33351e2 100644
--- a/src/libpmemobj/obj.c
+++ b/src/libpmemobj/obj.c
@@ -173,6 +173,7 @@ obj_ctl_init_and_load(PMEMobjpool *pop)
if (pop) {
tx_ctl_register(pop);
pmalloc_ctl_register(pop);
+ stats_ctl_register(pop);
}
char *env_config = os_getenv(OBJ_CONFIG_ENV_VARIABLE);
@@ -1097,6 +1098,13 @@ obj_runtime_init(PMEMobjpool *pop, int rdonly, int boot, unsigned nlanes)
return -1;
}
+ pop->stats = stats_new(pop);
+ if (pop->stats == NULL) {
+ tx_params_delete(pop->tx_params);
+ errno = ENOMEM;
+ return -1;
+ }
+
VALGRIND_REMOVE_PMEM_MAPPING(&pop->mutex_head,
sizeof(pop->mutex_head));
VALGRIND_REMOVE_PMEM_MAPPING(&pop->rwlock_head,
@@ -1109,8 +1117,7 @@ obj_runtime_init(PMEMobjpool *pop, int rdonly, int boot, unsigned nlanes)
if (boot) {
if ((errno = obj_boot(pop)) != 0)
- return -1;
-
+ goto err;
#ifdef USE_VG_MEMCHECK
if (On_valgrind) {
@@ -1152,6 +1159,7 @@ obj_runtime_init(PMEMobjpool *pop, int rdonly, int boot, unsigned nlanes)
return 0;
err:
+ stats_delete(pop, pop->stats);
tx_params_delete(pop->tx_params);
return -1;
@@ -1789,6 +1797,7 @@ obj_pool_cleanup(PMEMobjpool *pop)
{
LOG(3, "pop %p", pop);
+ stats_delete(pop, pop->stats);
tx_params_delete(pop->tx_params);
ctl_delete(pop->ctl);
diff --git a/src/libpmemobj/obj.h b/src/libpmemobj/obj.h
index 367877d3cef..461dedd5ffd 100644
--- a/src/libpmemobj/obj.h
+++ b/src/libpmemobj/obj.h
@@ -47,6 +47,7 @@
#include "ctl.h"
#include "ringbuf.h"
#include "sync.h"
+#include "stats.h"
#define PMEMOBJ_LOG_PREFIX "libpmemobj"
#define PMEMOBJ_LOG_LEVEL_VAR "PMEMOBJ_LOG_LEVEL"
@@ -135,7 +136,9 @@ struct pmemobjpool {
*/
uint64_t conversion_flags;
- char pmem_reserved[512]; /* must be zeroed */
+ struct stats_persistent stats_persistent;
+
+ char pmem_reserved[504]; /* must be zeroed */
/* some run-time state, allocated out of memory pool... */
void *addr; /* mapped region */
@@ -148,6 +151,7 @@ struct pmemobjpool {
int is_dev_dax; /* true if mapped on device dax */
struct ctl *ctl;
+ struct stats *stats;
struct ringbuf *tx_postcommit_tasks;
struct pool_set *set; /* pool set info */
@@ -191,7 +195,7 @@ struct pmemobjpool {
/* padding to align size of this structure to page boundary */
/* sizeof(unused2) == 8192 - offsetof(struct pmemobjpool, unused2) */
- char unused2[1012];
+ char unused2[996];
};
/*
diff --git a/src/libpmemobj/palloc.c b/src/libpmemobj/palloc.c
index c9d57b6ded2..69338ed1f02 100644
--- a/src/libpmemobj/palloc.c
+++ b/src/libpmemobj/palloc.c
@@ -288,8 +288,18 @@ palloc_finalize_heap_action(struct palloc_heap *heap,
const struct pobj_action_internal *act, int canceled)
{
if (act->new_state == MEMBLOCK_ALLOCATED) {
+ STATS_INC(heap->stats, persistent, heap_curr_allocated,
+ act->m.m_ops->get_real_size(&act->m));
+
palloc_reservation_finalize(heap, act, canceled);
} else if (!canceled && act->new_state == MEMBLOCK_FREE) {
+ if (heap->stats->enabled) {
+ struct memory_block m =
+ memblock_from_offset(heap, act->offset);
+ STATS_SUB(heap->stats, persistent, heap_curr_allocated,
+ m.m_ops->get_real_size(&m));
+ }
+
heap_memblock_on_free(heap, &act->m);
}
}
@@ -682,9 +692,11 @@ palloc_is_allocated(struct palloc_heap *heap, uint64_t off)
*/
int
palloc_boot(struct palloc_heap *heap, void *heap_start, uint64_t heap_size,
- uint64_t run_id, void *base, struct pmem_ops *p_ops)
+ uint64_t run_id, void *base, struct pmem_ops *p_ops,
+ struct stats *stats)
{
- return heap_boot(heap, heap_start, heap_size, run_id, base, p_ops);
+ return heap_boot(heap, heap_start, heap_size, run_id, base, p_ops,
+ stats);
}
/*
diff --git a/src/libpmemobj/palloc.h b/src/libpmemobj/palloc.h
index 29955d65660..16002b3f60b 100644
--- a/src/libpmemobj/palloc.h
+++ b/src/libpmemobj/palloc.h
@@ -44,6 +44,7 @@
#include "memops.h"
#include "redo.h"
#include "valgrind_internal.h"
+#include "stats.h"
struct palloc_heap {
struct pmem_ops p_ops;
@@ -51,6 +52,8 @@ struct palloc_heap {
struct heap_rt *rt;
uint64_t size;
+ struct stats *stats;
+
void *base;
};
@@ -93,7 +96,8 @@ uint16_t palloc_flags(struct palloc_heap *heap, uint64_t off);
int palloc_is_allocated(struct palloc_heap *heap, uint64_t off);
int palloc_boot(struct palloc_heap *heap, void *heap_start, uint64_t run_id,
- uint64_t heap_size, void *base, struct pmem_ops *p_ops);
+ uint64_t heap_size, void *base, struct pmem_ops *p_ops,
+ struct stats *stats);
int palloc_buckets_init(struct palloc_heap *heap);
int palloc_init(void *heap_start, uint64_t heap_size, struct pmem_ops *p_ops);
diff --git a/src/libpmemobj/pmalloc.c b/src/libpmemobj/pmalloc.c
index 3fcc9b493c0..6e7f70e2e20 100644
--- a/src/libpmemobj/pmalloc.c
+++ b/src/libpmemobj/pmalloc.c
@@ -273,7 +273,8 @@ static int
pmalloc_boot(PMEMobjpool *pop)
{
int ret = palloc_boot(&pop->heap, (char *)pop + pop->heap_offset,
- pop->heap_size, pop->run_id, pop, &pop->p_ops);
+ pop->heap_size, pop->run_id, pop, &pop->p_ops,
+ pop->stats);
if (ret)
return ret;
diff --git a/src/libpmemobj/stats.c b/src/libpmemobj/stats.c
new file mode 100644
index 00000000000..d22b4c3cdf9
--- /dev/null
+++ b/src/libpmemobj/stats.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2017, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * stats.c -- implementation of statistics
+ */
+
+#include "obj.h"
+#include "stats.h"
+
+STATS_CTL_HANDLER(persistent, curr_allocated, heap_curr_allocated);
+
+static const struct ctl_node CTL_NODE(heap)[] = {
+ STATS_CTL_LEAF(persistent, curr_allocated),
+
+ CTL_NODE_END
+};
+
+/*
+ * CTL_READ_HANDLER(enabled) -- returns whether or not statistics are enabled
+ */
+static int
+CTL_READ_HANDLER(enabled)(PMEMobjpool *pop,
+ enum ctl_query_source source, void *arg,
+ struct ctl_indexes *indexes)
+{
+ int *arg_out = arg;
+
+ *arg_out = pop->stats->enabled;
+
+ return 0;
+}
+
+/*
+ * CTL_WRITE_HANDLER(enabled) -- enables or disables statistics counting
+ */
+static int
+CTL_WRITE_HANDLER(enabled)(PMEMobjpool *pop,
+ enum ctl_query_source source, void *arg,
+ struct ctl_indexes *indexes)
+{
+ int arg_in = *(int *)arg;
+
+ pop->stats->enabled = arg_in;
+
+ return 0;
+}
+
+static struct ctl_argument CTL_ARG(enabled) = CTL_ARG_BOOLEAN;
+
+static const struct ctl_node CTL_NODE(stats)[] = {
+ CTL_CHILD(heap),
+ CTL_LEAF_RW(enabled),
+
+ CTL_NODE_END
+};
+
+/*
+ * stats_new -- allocates and initializes statistics instance
+ */
+struct stats *
+stats_new(PMEMobjpool *pop)
+{
+ struct stats *s = Malloc(sizeof(*s));
+ s->enabled = 0;
+ s->persistent = &pop->stats_persistent;
+ s->transient = Zalloc(sizeof(struct stats_transient));
+ if (s->transient == NULL)
+ goto error_transient_alloc;
+
+ return s;
+
+error_transient_alloc:
+ Free(s);
+ return NULL;
+}
+
+/*
+ * stats_delete -- deletes statistics instance
+ */
+void
+stats_delete(PMEMobjpool *pop, struct stats *s)
+{
+ pmemops_persist(&pop->p_ops, s->persistent,
+ sizeof(struct stats_persistent));
+ Free(s->transient);
+ Free(s);
+}
+
+/*
+ * stats_ctl_register -- registers ctl nodes for statistics
+ */
+void
+stats_ctl_register(PMEMobjpool *pop)
+{
+ CTL_REGISTER_MODULE(pop->ctl, stats);
+}
diff --git a/src/libpmemobj/stats.h b/src/libpmemobj/stats.h
new file mode 100644
index 00000000000..b6c143235f9
--- /dev/null
+++ b/src/libpmemobj/stats.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2017, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * stats.h -- definitions of statistics
+ */
+
+#ifndef LIBPMEMOBJ_STATS_H
+#define LIBPMEMOBJ_STATS_H 1
+
+#include "ctl.h"
+
+struct stats_transient {
+ int unused;
+};
+
+struct stats_persistent {
+ uint64_t heap_curr_allocated;
+};
+
+struct stats {
+ int enabled;
+ struct stats_transient *transient;
+ struct stats_persistent *persistent;
+};
+
+#define STATS_INC(stats, type, name, value) do {\
+ if (stats->enabled)\
+ util_fetch_and_add64((&stats->type->name), (value));\
+} while (0)
+
+#define STATS_SUB(stats, type, name, value) do {\
+ if (stats->enabled)\
+ util_fetch_and_sub64((&stats->type->name), (value));\
+} while (0)
+
+#define STATS_SET(stats, type, name, value) do {\
+ if (stats->enabled)\
+ util_atomic_store_explicit64((&stats->type->name), (value),\
+ memory_order_release);\
+} while (0)
+
+#define STATS_CTL_LEAF(type, name)\
+{CTL_STR(name), CTL_NODE_LEAF,\
+{CTL_READ_HANDLER(type##_##name), NULL, NULL},\
+NULL, NULL}
+
+#define STATS_CTL_HANDLER(type, name, varname)\
+static int CTL_READ_HANDLER(type##_##name)(PMEMobjpool *pop,\
+ enum ctl_query_source source, void *arg, struct ctl_indexes *indexes)\
+{\
+ uint64_t *argv = arg;\
+ util_atomic_load_explicit64(&pop->stats->type->varname,\
+ argv, memory_order_acquire);\
+ return 0;\
+}
+
+void stats_ctl_register(PMEMobjpool *pop);
+
+struct stats *stats_new(PMEMobjpool *pop);
+void stats_delete(PMEMobjpool *pop, struct stats *stats);
+
+#endif
diff --git a/src/test/Makefile.inc b/src/test/Makefile.inc
index 1a309db6ff5..a8a46ffcad5 100644
--- a/src/test/Makefile.inc
+++ b/src/test/Makefile.inc
@@ -126,7 +126,8 @@ OBJS += $(TOP)/src/debug/libpmemobj/alloc_class.o\
$(TOP)/src/debug/libpmemobj/redo.o\
$(TOP)/src/debug/libpmemobj/ringbuf.o\
$(TOP)/src/debug/libpmemobj/sync.o\
- $(TOP)/src/debug/libpmemobj/tx.o
+ $(TOP)/src/debug/libpmemobj/tx.o\
+ $(TOP)/src/debug/libpmemobj/stats.o
LIBS += $(LIBDL)
INCS += -I$(TOP)/src/libpmemobj
@@ -157,7 +158,8 @@ OBJS += $(TOP)/src/nondebug/libpmemobj/alloc_class.o\
$(TOP)/src/nondebug/libpmemobj/redo.o\
$(TOP)/src/nondebug/libpmemobj/ringbuf.o\
$(TOP)/src/nondebug/libpmemobj/sync.o\
- $(TOP)/src/nondebug/libpmemobj/tx.o
+ $(TOP)/src/nondebug/libpmemobj/tx.o\
+ $(TOP)/src/nondebug/libpmemobj/stats.o
INCS += -I$(TOP)/src/libpmemobj
LIBPMEM=y
diff --git a/src/test/obj_bucket/obj_bucket.vcxproj b/src/test/obj_bucket/obj_bucket.vcxproj
index e66930f9f60..4023df184fb 100644
--- a/src/test/obj_bucket/obj_bucket.vcxproj
+++ b/src/test/obj_bucket/obj_bucket.vcxproj
@@ -48,6 +48,7 @@
+
NDEBUG;_CONSOLE;%(PreprocessorDefinitions);WRAP_REAL
_DEBUG;_CONSOLE;%(PreprocessorDefinitions);WRAP_REAL
@@ -106,4 +107,4 @@
-
\ No newline at end of file
+
diff --git a/src/test/obj_ctl_prefault/obj_ctl_prefault.c b/src/test/obj_ctl_prefault/obj_ctl_prefault.c
index 650d965c17a..1498c07941c 100644
--- a/src/test/obj_ctl_prefault/obj_ctl_prefault.c
+++ b/src/test/obj_ctl_prefault/obj_ctl_prefault.c
@@ -99,7 +99,7 @@ main(int argc, char *argv[])
if ((pop = pmemobj_open(path, LAYOUT)) == NULL)
UT_FATAL("!pmemobj_open: %s", path);
} else {
- if ((pop = pmemobj_create(path, LAYOUT, PMEMOBJ_MIN_POOL,
+ if ((pop = pmemobj_create(path, LAYOUT, 0,
S_IWUSR | S_IRUSR)) == NULL)
UT_FATAL("!pmemobj_create: %s", path);
}
diff --git a/src/test/obj_ctl_stats/.gitignore b/src/test/obj_ctl_stats/.gitignore
new file mode 100644
index 00000000000..9ff0d30364c
--- /dev/null
+++ b/src/test/obj_ctl_stats/.gitignore
@@ -0,0 +1 @@
+obj_ctl_stats
diff --git a/src/test/obj_ctl_stats/Makefile b/src/test/obj_ctl_stats/Makefile
new file mode 100644
index 00000000000..93fae506c24
--- /dev/null
+++ b/src/test/obj_ctl_stats/Makefile
@@ -0,0 +1,42 @@
+#
+# Copyright 2017, Intel Corporation
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# * Neither the name of the copyright holder nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+#
+# src/test/obj_ctl_stats/Makefile -- build obj_ctl_stats test
+#
+TARGET = obj_ctl_stats
+OBJS = obj_ctl_stats.o
+
+LIBPMEM=y
+LIBPMEMOBJ=y
+
+include ../Makefile.inc
diff --git a/src/test/obj_ctl_stats/TEST0 b/src/test/obj_ctl_stats/TEST0
new file mode 100755
index 00000000000..aafbf71fccf
--- /dev/null
+++ b/src/test/obj_ctl_stats/TEST0
@@ -0,0 +1,47 @@
+#!/usr/bin/env bash
+#
+# Copyright 2017, Intel Corporation
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# * Neither the name of the copyright holder nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+export UNITTEST_NAME=obj_ctl_stats/TEST0
+export UNITTEST_NUM=0
+
+# standard unit test setup
+. ../unittest/unittest.sh
+
+require_test_type short
+require_fs_type any
+
+setup
+
+expect_normal_exit ./obj_ctl_stats$EXESUFFIX $DIR/testfile1
+
+pass
diff --git a/src/test/obj_ctl_stats/obj_ctl_stats.c b/src/test/obj_ctl_stats/obj_ctl_stats.c
new file mode 100644
index 00000000000..25082558796
--- /dev/null
+++ b/src/test/obj_ctl_stats/obj_ctl_stats.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2017, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * obj_ctl_stats.c -- tests for the libpmemobj statistics module
+ */
+
+#include "unittest.h"
+
+int
+main(int argc, char *argv[])
+{
+ START(argc, argv, "obj_ctl_stats");
+
+ if (argc != 2)
+ UT_FATAL("usage: %s file-name", argv[0]);
+
+ const char *path = argv[1];
+
+ PMEMobjpool *pop;
+ if ((pop = pmemobj_create(path, "ctl", PMEMOBJ_MIN_POOL,
+ S_IWUSR | S_IRUSR)) == NULL)
+ UT_FATAL("!pmemobj_create: %s", path);
+
+ int enabled;
+ int ret = pmemobj_ctl_get(pop, "stats.enabled", &enabled);
+ UT_ASSERTeq(enabled, 0);
+ UT_ASSERTeq(ret, 0);
+
+ ret = pmemobj_alloc(pop, NULL, 1, 0, NULL, NULL);
+ UT_ASSERTeq(ret, 0);
+
+ size_t allocated;
+ ret = pmemobj_ctl_get(pop, "stats.heap.curr_allocated", &allocated);
+ UT_ASSERTeq(allocated, 0);
+
+ enabled = 1;
+ ret = pmemobj_ctl_set(pop, "stats.enabled", &enabled);
+ UT_ASSERTeq(ret, 0);
+
+ PMEMoid oid;
+ ret = pmemobj_alloc(pop, &oid, 1, 0, NULL, NULL);
+ UT_ASSERTeq(ret, 0);
+ size_t oid_size = pmemobj_alloc_usable_size(oid) + 16;
+
+ ret = pmemobj_ctl_get(pop, "stats.heap.curr_allocated", &allocated);
+ UT_ASSERTeq(ret, 0);
+ UT_ASSERTeq(allocated, oid_size);
+
+ pmemobj_free(&oid);
+
+ ret = pmemobj_ctl_get(pop, "stats.heap.curr_allocated", &allocated);
+ UT_ASSERTeq(ret, 0);
+ UT_ASSERTeq(allocated, 0);
+
+ pmemobj_close(pop);
+
+ DONE(NULL);
+}
diff --git a/src/test/obj_heap/obj_heap.c b/src/test/obj_heap/obj_heap.c
index 3deb60fcc7b..e005eb718bc 100644
--- a/src/test/obj_heap/obj_heap.c
+++ b/src/test/obj_heap/obj_heap.c
@@ -215,6 +215,9 @@ test_heap(void)
pop->p_ops.base = pop;
pop->p_ops.pool_size = pop->size;
+ struct stats *s = stats_new(pop);
+ UT_ASSERTne(s, NULL);
+
void *heap_start = (char *)pop + pop->heap_offset;
uint64_t heap_size = pop->heap_size;
struct palloc_heap *heap = &pop->heap;
@@ -223,7 +226,7 @@ test_heap(void)
UT_ASSERT(heap_check(heap_start, heap_size) != 0);
UT_ASSERT(heap_init(heap_start, heap_size, p_ops) == 0);
UT_ASSERT(heap_boot(heap, heap_start, heap_size, TEST_RUN_ID,
- pop, p_ops) == 0);
+ pop, p_ops, s) == 0);
UT_ASSERT(heap_buckets_init(heap) == 0);
UT_ASSERT(pop->heap.rt != NULL);
@@ -282,6 +285,7 @@ test_heap(void)
heap_bucket_release(heap, b_run);
+ stats_delete(pop, s);
UT_ASSERT(heap_check(heap_start, heap_size) == 0);
heap_cleanup(heap);
UT_ASSERT(heap->rt == NULL);
@@ -309,10 +313,13 @@ test_recycler(void)
struct palloc_heap *heap = &pop->heap;
struct pmem_ops *p_ops = &pop->p_ops;
+ struct stats *s = stats_new(pop);
+ UT_ASSERTne(s, NULL);
+
UT_ASSERT(heap_check(heap_start, heap_size) != 0);
UT_ASSERT(heap_init(heap_start, heap_size, p_ops) == 0);
UT_ASSERT(heap_boot(heap, heap_start, heap_size, TEST_RUN_ID,
- pop, p_ops) == 0);
+ pop, p_ops, s) == 0);
UT_ASSERT(heap_buckets_init(heap) == 0);
UT_ASSERT(pop->heap.rt != NULL);
@@ -424,6 +431,7 @@ test_recycler(void)
recycler_delete(r);
+ stats_delete(pop, s);
heap_cleanup(heap);
UT_ASSERT(heap->rt == NULL);
diff --git a/src/test/obj_heap/obj_heap.vcxproj b/src/test/obj_heap/obj_heap.vcxproj
index 261709c3eb1..dcf18ecce41 100644
--- a/src/test/obj_heap/obj_heap.vcxproj
+++ b/src/test/obj_heap/obj_heap.vcxproj
@@ -22,6 +22,8 @@
+
+
diff --git a/src/test/obj_heap_interrupt/obj_heap_interrupt.vcxproj b/src/test/obj_heap_interrupt/obj_heap_interrupt.vcxproj
index f3d9b053e2c..2e77ff1b971 100644
--- a/src/test/obj_heap_interrupt/obj_heap_interrupt.vcxproj
+++ b/src/test/obj_heap_interrupt/obj_heap_interrupt.vcxproj
@@ -37,6 +37,7 @@
+
_DEBUG;_CONSOLE;%(PreprocessorDefinitions);WRAP_REAL
NDEBUG;_CONSOLE;%(PreprocessorDefinitions);WRAP_REAL
@@ -111,4 +112,4 @@
-
\ No newline at end of file
+
diff --git a/src/test/obj_list/obj_list.vcxproj b/src/test/obj_list/obj_list.vcxproj
index a52adf64272..697b241d2cf 100644
--- a/src/test/obj_list/obj_list.vcxproj
+++ b/src/test/obj_list/obj_list.vcxproj
@@ -63,6 +63,7 @@
+
_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
@@ -139,4 +140,4 @@
-
\ No newline at end of file
+
diff --git a/src/test/obj_memblock/obj_memblock.vcxproj b/src/test/obj_memblock/obj_memblock.vcxproj
index 9ddd9f1a962..769e4972fc0 100644
--- a/src/test/obj_memblock/obj_memblock.vcxproj
+++ b/src/test/obj_memblock/obj_memblock.vcxproj
@@ -46,6 +46,7 @@
+
@@ -108,4 +109,4 @@
-
\ No newline at end of file
+
diff --git a/src/test/obj_persist_count/obj_persist_count.vcxproj b/src/test/obj_persist_count/obj_persist_count.vcxproj
index 874870794ee..bbfa4878466 100644
--- a/src/test/obj_persist_count/obj_persist_count.vcxproj
+++ b/src/test/obj_persist_count/obj_persist_count.vcxproj
@@ -56,6 +56,7 @@
+
_DEBUG;_CONSOLE;%(PreprocessorDefinitions);WRAP_REAL
NDEBUG;_CONSOLE;%(PreprocessorDefinitions);WRAP_REAL
diff --git a/src/test/obj_pmalloc_basic/obj_pmalloc_basic.c b/src/test/obj_pmalloc_basic/obj_pmalloc_basic.c
index c6f85cce088..9cadbc0398f 100644
--- a/src/test/obj_pmalloc_basic/obj_pmalloc_basic.c
+++ b/src/test/obj_pmalloc_basic/obj_pmalloc_basic.c
@@ -314,9 +314,12 @@ test_mock_pool_allocs(void)
void *heap_start = (char *)mock_pop + mock_pop->heap_offset;
uint64_t heap_size = mock_pop->heap_size;
+ struct stats *s = stats_new(mock_pop);
+ UT_ASSERTne(s, NULL);
+
heap_init(heap_start, heap_size, &mock_pop->p_ops);
heap_boot(&mock_pop->heap, heap_start, heap_size, MOCK_RUN_ID, mock_pop,
- &mock_pop->p_ops);
+ &mock_pop->p_ops, s);
heap_buckets_init(&mock_pop->heap);
/* initialize runtime lanes structure */
@@ -364,6 +367,7 @@ test_mock_pool_allocs(void)
test_realloc(TEST_SMALL_ALLOC_SIZE, TEST_MEDIUM_ALLOC_SIZE);
test_realloc(TEST_HUGE_ALLOC_SIZE, TEST_MEGA_ALLOC_SIZE);
+ stats_delete(mock_pop, s);
lane_cleanup(mock_pop);
redo_log_config_delete(mock_pop->redo);
heap_cleanup(&mock_pop->heap);
diff --git a/src/test/obj_pmalloc_basic/obj_pmalloc_basic.vcxproj b/src/test/obj_pmalloc_basic/obj_pmalloc_basic.vcxproj
index 0c32e17d4fe..98a0bd7f113 100644
--- a/src/test/obj_pmalloc_basic/obj_pmalloc_basic.vcxproj
+++ b/src/test/obj_pmalloc_basic/obj_pmalloc_basic.vcxproj
@@ -45,6 +45,7 @@
+
@@ -100,4 +101,4 @@
-
\ No newline at end of file
+
diff --git a/src/test/obj_pmalloc_mt/obj_pmalloc_mt.vcxproj b/src/test/obj_pmalloc_mt/obj_pmalloc_mt.vcxproj
index 23d95f7c6db..b27bfbc5245 100644
--- a/src/test/obj_pmalloc_mt/obj_pmalloc_mt.vcxproj
+++ b/src/test/obj_pmalloc_mt/obj_pmalloc_mt.vcxproj
@@ -45,6 +45,7 @@
+
@@ -100,4 +101,4 @@
-
\ No newline at end of file
+
diff --git a/src/test/obj_pvector/obj_pvector.vcxproj b/src/test/obj_pvector/obj_pvector.vcxproj
index abf5dafa1c4..993fe4ae19e 100644
--- a/src/test/obj_pvector/obj_pvector.vcxproj
+++ b/src/test/obj_pvector/obj_pvector.vcxproj
@@ -84,6 +84,7 @@
+
@@ -106,4 +107,4 @@
-
\ No newline at end of file
+
diff --git a/src/test/obj_realloc/obj_realloc.vcxproj b/src/test/obj_realloc/obj_realloc.vcxproj
index 55950f671cc..6c47c31e92c 100644
--- a/src/test/obj_realloc/obj_realloc.vcxproj
+++ b/src/test/obj_realloc/obj_realloc.vcxproj
@@ -149,6 +149,10 @@
CompileAsC
CompileAsC
+
+ CompileAsC
+ CompileAsC
+
CompileAsC
CompileAsC
diff --git a/src/test/obj_ringbuf/obj_ringbuf.vcxproj b/src/test/obj_ringbuf/obj_ringbuf.vcxproj
index 550790b17d6..42b1b8c5510 100644
--- a/src/test/obj_ringbuf/obj_ringbuf.vcxproj
+++ b/src/test/obj_ringbuf/obj_ringbuf.vcxproj
@@ -84,6 +84,7 @@
+
@@ -106,4 +107,4 @@
-
\ No newline at end of file
+
diff --git a/src/test/obj_ringbuf/obj_ringbuf.vcxproj.filters b/src/test/obj_ringbuf/obj_ringbuf.vcxproj.filters
index b2226432fcd..8b14a7be872 100644
--- a/src/test/obj_ringbuf/obj_ringbuf.vcxproj.filters
+++ b/src/test/obj_ringbuf/obj_ringbuf.vcxproj.filters
@@ -7,6 +7,9 @@
Source Files
+
+ Source Files
+
Source Files
@@ -90,4 +93,4 @@
Test Scripts
-
\ No newline at end of file
+
diff --git a/src/tools/pmempool/pmempool.vcxproj b/src/tools/pmempool/pmempool.vcxproj
index 0c4a722323c..535e7f114eb 100644
--- a/src/tools/pmempool/pmempool.vcxproj
+++ b/src/tools/pmempool/pmempool.vcxproj
@@ -15,6 +15,7 @@
+
diff --git a/src/tools/pmempool/pmempool.vcxproj.filters b/src/tools/pmempool/pmempool.vcxproj.filters
index b0af7648604..4459573843d 100644
--- a/src/tools/pmempool/pmempool.vcxproj.filters
+++ b/src/tools/pmempool/pmempool.vcxproj.filters
@@ -65,6 +65,9 @@
libs
+
+ libs
+
libs