---
name: "mmv_stats_registry"
section: "3"
platform: "linux"
package: "pcp"
version: "7.2.2-2"
release: "Arch Linux 2026-11-01"
platforms: ["linux"]
url: "https://new.carta.tech/mmv_stats_registry"
---

# mmv\_stats\_registry(3)

Initialize the Memory Mapped Value file

## NAME

**mmv\_stats\_registry**, **mmv\_stats\_start**, **mmv\_stats\_stop** - Initialize the Memory Mapped Value file

## C SYNOPSIS

**#include \<pcp/pmapi.h\>**\
 **#include \<pcp/mmv\_stats.h\>**

**mmv\_registry\_t \*mmv\_stats\_registry(const char \****file***,** **int** *cluster***,** **mmv\_stats\_flags\_t** *flags***);**\
 **void \*mmv\_stats\_start(mmv\_registry\_t \****registry***);**\
 **void mmv\_stats\_stop(const char \****fname***,** **void \****addr***);**

**cc ... -lpcp\_mmv -lpcp**

## DESCRIPTION

**mmv\_stats\_registry** initializes an opaque structure that defines various aspects of a memory mapped file. This file is used for lightweight interprocess communication between an instrumented application and [*pmdammv*(1)](/pmdammv/1.md).

The **mmv\_stats\_registry** interface is used to allocate a registry, and allows the *name* of the *MMV*(5) file, the *cluster* identifier and the *flags* (if any) to be set. It returns a handle that is used in subsequent MMV API calls when adding metrics, indoms, instances and labels to the registry - before actually creating the file.

**mmv\_stats\_start** is the call that creates the *MMV*(5) file with the handle that returns **mmv\_stats\_registry**. It returns the mapped memory handle used in subsequent MMV API calls, such as [**mmv\_inc\_value**(3)](/mmv_inc_value/3.md).

**mmv\_stats\_stop** performs an orderly shutdown of the mapping handle returned by an earlier initialization call and also frees the registry structure.

The combination of **mmv\_stats\_registry** and **mmv\_stats\_start** do the same as the deprecated calls **mmv\_stats2\_init**. However, now, one should first call **mmv\_stats\_registry** and then the API calls that add instances, indoms, metrics and labels. In this way, there is no need to know in advance which version of the MMV(1\|2\|3) mapping will be used as it is calculated automatically.

The file is created in the *$PCP\_TMP\_DIR/mmv* directory, the *name* argument is expected to be a basename of the file, not the full path. The metadata content of the file does not change after the file has been created.

The old file is removed unconditionally unless there was an error.

*cluster* is the preferred MMV PMDA cluster ID to be used for the metrics the originates the call **mmv\_stats\_start**. The *flags* provide additional control over the behaviour of the MMV PMDA - e.g. use of MMV\_FLAG\_PROCESS will ensure values are only exported when the instrumented application is running - this is verified on each request for new values.

The next sections explain how to add metrics, indoms, instances and labels.

## ADD METRICS

**int mmv\_stats\_add\_metric(mmv\_registry\_t \*registry,** **const char \****name***,** **int** *item***,** **mmv\_metric\_type\_t** *type***,** **mmv\_metric\_sem\_t** *sem***,** **pmUnits** *units***,** **int** *serial***,** **const char \****shorthelp***,** **const char \****longhelp***);**

When adding a metric, internally it is being handled using the next struct. *sem* match in the struct is semantics. *units* match in the struct is dimension. *serial* match in the struct is indom.

```
        typedef struct {
            char *name;                 /* Name of the metric */
            __uint32_t item;            /* Item component of PMID */
            mmv_metric_type_t type;     /* Type of the metric */
            mmv_metric_sem_t semantics; /* Semantics of the metric */
            pmUnits dimension;          /* Dimensions (TIME,SPACE,etc) */
            __uint32_t indom;           /* Instance domain identifier */
            char *shorttext;            /* Optional, one-line help */
            char *helptext;             /* Optional, full help text */
        } mmv_metric2_t;
```

## ADD INDOMS

**int mmv\_stats\_add\_indom(mmv\_registry\_t \****registry***,** **int** *serial***,** **const char \****shorthelp***,** **const char \****longhelp***);**

When adding an indom, internally it is being handled using the next struct.

```
        typedef struct {
            __uint32_t serial;           /* Unique serial number */
            __uint32_t count;            /* Number of instances */
            mmv_instances2_t *instances; /* Internal/external IDs */
            char *shorttext;             /* Short help text */
            char *helptext;              /* Long help text */
        } mmv_indom2_t;
```

## ADD INSTANCES

**int mmv\_stats\_add\_instance(mmv\_registry\_t \****registry***,** **int** *serial***,** **int** *instid***,** **const char \****instname***);**

When adding an instance, internally it is being handled using the next struct. *instid* match in the struct is internal while *instname* is external.

```
        typedef struct {
            __int32_t internal;
            char *external;
        } mmv_instances2_t;
```

It is worth mentioning that if the indom of the instance is not found it returns an error.

## ADD LABELS

**int mmv\_stats\_add\_registry\_label(mmv\_registry\_t \****registry***,** **const char \****name***,** **const char \****value***,** **mmv\_value\_type\_t** *type***,** **int** *optional***);**

**int mmv\_stats\_add\_indom\_label(mmv\_registry\_t \****registry***,** **int** *serial***,** **const char \****name***,** **const char \****value***,** **mmv\_value\_type\_t** *type***,** **int** *optional***);**

**int mmv\_stats\_add\_metric\_label(mmv\_registry\_t \****registry***,** **int** *item***,** **const char \****name***,** **const char \****value***,** **mmv\_value\_type\_t** *type***,** **int** *optional***);**

**int mmv\_stats\_add\_instance\_label(mmv\_registry\_t \****registry***,** **int** *serial***,** **int** *instid***,** **const char \****name***,** **const char \****value***,** **mmv\_value\_type\_t** *type***,** **int** *optional***);**

*registry* is the handle obtained from **mmv\_stats\_registry**. *name* and *value* are the strings that will form the label.

*type* specifies the value type that can be: MMV\_STRING\_TYPE, MMV\_NUMBER\_TYPE, MMV\_BOOLEAN\_TYPE, MMV\_NULL\_TYPE, MMV\_ARRAY\_TYPE and MMV\_MAP\_TYPE.

At the moment there is a simple check of the correctness of the value. After adding a label, it is called a function to verify if it is correct.

Additionally, if *optional* is set, it is added the flag PM\_LABEL\_OPTIONAL.

*serial* is the serial of the indom when adding an indom or instance label. *item* is the metric identifier when adding a metric label. Finally, when adding a registry label it is not necessary to give the cluster id because it will be taken from the internal registry struct already created.

**mmv\_stats\_add\_registry\_label** adds a PM\_LABEL\_CLUSTER.

**mmv\_stats\_add\_indom\_label** adds a PM\_LABEL\_INDOM.

**mmv\_stats\_add\_metric\_label** adds a PM\_LABEL\_ITEM.

**mmv\_stats\_add\_instance\_label** adds a PM\_LABEL\_INSTANCES.

## RETURN VALUES

 When adding metrics, indoms, instances and labels, if correct returns 0\
  and if not it returns an errno code. The other functions return the address\
  of the memory mapped region on success. On failure, NULL is returned and\
  *errno* is set to a value suitable for decoding with [**strerror**(3)](/strerror/3.md).

## SEE ALSO

[**mmv\_inc\_value**(3)](/mmv_inc_value/3.md), [**mmv\_lookup\_value\_desc**(3)](/mmv_lookup_value_desc/3.md), [**strerror**(3)](/strerror/3.md) and [**mmv**(5)](/mmv/5.md).
