get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/75817/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 75817,
    "url": "http://patches.dpdk.org/api/patches/75817/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20200821125115.52998-2-ciara.power@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20200821125115.52998-2-ciara.power@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200821125115.52998-2-ciara.power@intel.com",
    "date": "2020-08-21T12:51:13",
    "name": "[v8,1/3] telemetry: support array values in data objects",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "f13034fdb4e53f698dff57c028f502e79bff367a",
    "submitter": {
        "id": 978,
        "url": "http://patches.dpdk.org/api/people/978/?format=api",
        "name": "Ciara Power",
        "email": "ciara.power@intel.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20200821125115.52998-2-ciara.power@intel.com/mbox/",
    "series": [
        {
            "id": 11742,
            "url": "http://patches.dpdk.org/api/series/11742/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=11742",
            "date": "2020-08-21T12:51:12",
            "name": "add basic ethdev stats with data object recursion",
            "version": 8,
            "mbox": "http://patches.dpdk.org/series/11742/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/75817/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/75817/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 9B92BA04AF;\n\tFri, 21 Aug 2020 15:00:45 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 162D71C0BD;\n\tFri, 21 Aug 2020 15:00:41 +0200 (CEST)",
            "from mga17.intel.com (mga17.intel.com [192.55.52.151])\n by dpdk.org (Postfix) with ESMTP id 4E24A1C0B7\n for <dev@dpdk.org>; Fri, 21 Aug 2020 15:00:39 +0200 (CEST)",
            "from orsmga005.jf.intel.com ([10.7.209.41])\n by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 21 Aug 2020 06:00:36 -0700",
            "from silpixa00399953.ir.intel.com (HELO\n silpixa00399953.ger.corp.intel.com) ([10.237.222.53])\n by orsmga005.jf.intel.com with ESMTP; 21 Aug 2020 06:00:34 -0700"
        ],
        "IronPort-SDR": [
            "\n 3l667yzvawdiCCu11YCeBsC4f4z7i0NdLJrLognqNAbWy5nykMD1NsFgWrfACW92lPOeOsZ5Dx\n uKUncwiMWF+A==",
            "\n 74xecdsEpgPYyalwZ7eXXlb3+g1Okg6NvGLfpDwUUCidU6YCB3wRlpyw09cjUDEQIozxOQutxA\n JurjIAwA3oaw=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6000,8403,9719\"; a=\"135584585\"",
            "E=Sophos;i=\"5.76,335,1592895600\"; d=\"scan'208\";a=\"135584585\"",
            "E=Sophos;i=\"5.76,335,1592895600\"; d=\"scan'208\";a=\"473039081\""
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "From": "Ciara Power <ciara.power@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "keith.wiles@intel.com, bruce.richardson@intel.com,\n Ciara Power <ciara.power@intel.com>, Kevin Laatz <kevin.laatz@intel.com>,\n Ray Kinsella <mdr@ashroe.eu>, Neil Horman <nhorman@tuxdriver.com>",
        "Date": "Fri, 21 Aug 2020 13:51:13 +0100",
        "Message-Id": "<20200821125115.52998-2-ciara.power@intel.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20200821125115.52998-1-ciara.power@intel.com>",
        "References": "<20200612105344.15383-1-ciara.power@intel.com>\n <20200821125115.52998-1-ciara.power@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v8 1/3] telemetry: support array values in data\n\tobjects",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Arrays of type uint64_t/int/string can now be included within an array\nor dict. One level of embedded containers is supported. This is\nnecessary to allow for instances such as the ethdev queue stats to be\nreported as a list of uint64_t values, rather than having multiple dict\nentries with one uint64_t value for each queue stat.\n\nThe memory management APIs provided by telemetry simplify the memory\nallocation/free aspect of the embedded container. The rte_tel_data_alloc\nfunction is called in the library/app callback to return a pointer to a\ncontainer that has been allocated memory. When adding this container\nto an array/dict, a parameter is passed to indicate if the memory\nshould be freed by telemetry after use. This will allow reuse of the\nallocated memory if the library/app wishes to do so.\n\nSigned-off-by: Ciara Power <ciara.power@intel.com>\nAcked-by: Bruce Richardson <bruce.richardson@intel.com>\n---\n lib/librte_telemetry/rte_telemetry.h          | 70 +++++++++++++++++++\n .../rte_telemetry_version.map                 |  4 ++\n lib/librte_telemetry/telemetry.c              | 56 +++++++++++++++\n lib/librte_telemetry/telemetry_data.c         | 51 ++++++++++++++\n lib/librte_telemetry/telemetry_data.h         |  7 ++\n lib/librte_telemetry/telemetry_json.h         | 33 +++++++++\n 6 files changed, 221 insertions(+)",
    "diff": "diff --git a/lib/librte_telemetry/rte_telemetry.h b/lib/librte_telemetry/rte_telemetry.h\nindex d13010b8fb..c165412260 100644\n--- a/lib/librte_telemetry/rte_telemetry.h\n+++ b/lib/librte_telemetry/rte_telemetry.h\n@@ -46,6 +46,7 @@ enum rte_tel_value_type {\n \tRTE_TEL_STRING_VAL, /** a string value */\n \tRTE_TEL_INT_VAL,    /** a signed 32-bit int value */\n \tRTE_TEL_U64_VAL,    /** an unsigned 64-bit int value */\n+\tRTE_TEL_CONTAINER, /** a container struct */\n };\n \n /**\n@@ -136,6 +137,28 @@ __rte_experimental\n int\n rte_tel_data_add_array_u64(struct rte_tel_data *d, uint64_t x);\n \n+/**\n+ * Add a container to an array. A container is an existing telemetry data\n+ * array. The array the container is to be added to must have been started by\n+ * rte_tel_data_start_array() with RTE_TEL_CONTAINER as the type parameter.\n+ * The container type must be an array of type uint64_t/int/string.\n+ *\n+ * @param d\n+ *   The data structure passed to the callback\n+ * @param val\n+ *   The pointer to the container to be stored in the array.\n+ * @param keep\n+ *   Flag to indicate that the container memory should not be automatically\n+ *   freed by the telemetry library once it has finished with the data.\n+ *   1 = keep, 0 = free.\n+ * @return\n+ *   0 on success, negative errno on error\n+ */\n+__rte_experimental\n+int\n+rte_tel_data_add_array_container(struct rte_tel_data *d,\n+\t\tstruct rte_tel_data *val, int keep);\n+\n /**\n  * Add a string value to a dictionary.\n  * The dict must have been started by rte_tel_data_start_dict().\n@@ -190,6 +213,30 @@ int\n rte_tel_data_add_dict_u64(struct rte_tel_data *d,\n \t\tconst char *name, uint64_t val);\n \n+/**\n+ * Add a container to a dictionary. A container is an existing telemetry data\n+ * array. The dict the container is to be added to must have been started by\n+ * rte_tel_data_start_dict(). The container must be an array of type\n+ * uint64_t/int/string.\n+ *\n+ * @param d\n+ *   The data structure passed to the callback\n+ * @param name\n+ *   The name the value is to be stored under in the dict.\n+ * @param val\n+ *   The pointer to the container to be stored in the dict.\n+ * @param keep\n+ *   Flag to indicate that the container memory should not be automatically\n+ *   freed by the telemetry library once it has finished with the data.\n+ *   1 = keep, 0 = free.\n+ * @return\n+ *   0 on success, negative errno on error\n+ */\n+__rte_experimental\n+int\n+rte_tel_data_add_dict_container(struct rte_tel_data *d, const char *name,\n+\t\tstruct rte_tel_data *val, int keep);\n+\n /**\n  * This telemetry callback is used when registering a telemetry command.\n  * It handles getting and formatting information to be returned to telemetry\n@@ -264,4 +311,27 @@ int\n rte_telemetry_init(const char *runtime_dir, rte_cpuset_t *cpuset,\n \t\tconst char **err_str);\n \n+/**\n+ * Get a pointer to a container with memory allocated. The container is to be\n+ * used embedded within an existing telemetry dict/array.\n+ *\n+ * @return\n+ *  Pointer to a container.\n+ */\n+__rte_experimental\n+struct rte_tel_data *\n+rte_tel_data_alloc(void);\n+\n+/**\n+ * @internal\n+ * Free a container that has memory allocated.\n+ *\n+ * @param data\n+ *  Pointer to container.\n+ *.\n+ */\n+__rte_experimental\n+void\n+rte_tel_data_free(struct rte_tel_data *data);\n+\n #endif\ndiff --git a/lib/librte_telemetry/rte_telemetry_version.map b/lib/librte_telemetry/rte_telemetry_version.map\nindex 86433c21d0..d1dbf8d586 100644\n--- a/lib/librte_telemetry/rte_telemetry_version.map\n+++ b/lib/librte_telemetry/rte_telemetry_version.map\n@@ -1,12 +1,16 @@\n EXPERIMENTAL {\n \tglobal:\n \n+\trte_tel_data_add_array_container;\n \trte_tel_data_add_array_int;\n \trte_tel_data_add_array_string;\n \trte_tel_data_add_array_u64;\n+\trte_tel_data_add_dict_container;\n \trte_tel_data_add_dict_int;\n \trte_tel_data_add_dict_string;\n \trte_tel_data_add_dict_u64;\n+\trte_tel_data_alloc;\n+\trte_tel_data_free;\n \trte_tel_data_start_array;\n \trte_tel_data_start_dict;\n \trte_tel_data_string;\ndiff --git a/lib/librte_telemetry/telemetry.c b/lib/librte_telemetry/telemetry.c\nindex 0252282735..4469885c34 100644\n--- a/lib/librte_telemetry/telemetry.c\n+++ b/lib/librte_telemetry/telemetry.c\n@@ -123,6 +123,35 @@ command_help(const char *cmd __rte_unused, const char *params,\n \treturn 0;\n }\n \n+static int\n+container_to_json(const struct rte_tel_data *d, char *out_buf, size_t buf_len)\n+{\n+\tsize_t used = 0;\n+\tunsigned int i;\n+\n+\tif (d->type != RTE_TEL_ARRAY_U64 && d->type != RTE_TEL_ARRAY_INT\n+\t\t\t&& d->type != RTE_TEL_ARRAY_STRING)\n+\t\treturn snprintf(out_buf, buf_len, \"null\");\n+\n+\tused = rte_tel_json_empty_array(out_buf, buf_len, 0);\n+\tif (d->type == RTE_TEL_ARRAY_U64)\n+\t\tfor (i = 0; i < d->data_len; i++)\n+\t\t\tused = rte_tel_json_add_array_u64(out_buf,\n+\t\t\t\tbuf_len, used,\n+\t\t\t\td->data.array[i].u64val);\n+\tif (d->type == RTE_TEL_ARRAY_INT)\n+\t\tfor (i = 0; i < d->data_len; i++)\n+\t\t\tused = rte_tel_json_add_array_int(out_buf,\n+\t\t\t\tbuf_len, used,\n+\t\t\t\td->data.array[i].ival);\n+\tif (d->type == RTE_TEL_ARRAY_STRING)\n+\t\tfor (i = 0; i < d->data_len; i++)\n+\t\t\tused = rte_tel_json_add_array_string(out_buf,\n+\t\t\t\tbuf_len, used,\n+\t\t\t\td->data.array[i].sval);\n+\treturn used;\n+}\n+\n static void\n output_json(const char *cmd, const struct rte_tel_data *d, int s)\n {\n@@ -169,6 +198,20 @@ output_json(const char *cmd, const struct rte_tel_data *d, int s)\n \t\t\t\t\t\tbuf_len, used,\n \t\t\t\t\t\tv->name, v->value.u64val);\n \t\t\t\tbreak;\n+\t\t\tcase RTE_TEL_CONTAINER:\n+\t\t\t{\n+\t\t\t\tchar temp[buf_len];\n+\t\t\t\tconst struct container *cont =\n+\t\t\t\t\t\t&v->value.container;\n+\t\t\t\tif (container_to_json(cont->data,\n+\t\t\t\t\t\ttemp, buf_len) != 0)\n+\t\t\t\t\tused = rte_tel_json_add_obj_json(\n+\t\t\t\t\t\t\tcb_data_buf,\n+\t\t\t\t\t\t\tbuf_len, used,\n+\t\t\t\t\t\t\tv->name, temp);\n+\t\t\t\tif (!cont->keep)\n+\t\t\t\t\trte_tel_data_free(cont->data);\n+\t\t\t}\n \t\t\t}\n \t\t}\n \t\tused += prefix_used;\n@@ -177,6 +220,7 @@ output_json(const char *cmd, const struct rte_tel_data *d, int s)\n \tcase RTE_TEL_ARRAY_STRING:\n \tcase RTE_TEL_ARRAY_INT:\n \tcase RTE_TEL_ARRAY_U64:\n+\tcase RTE_TEL_ARRAY_CONTAINER:\n \t\tprefix_used = snprintf(out_buf, sizeof(out_buf), \"{\\\"%.*s\\\":\",\n \t\t\t\tMAX_CMD_LEN, cmd);\n \t\tcb_data_buf = &out_buf[prefix_used];\n@@ -197,6 +241,18 @@ output_json(const char *cmd, const struct rte_tel_data *d, int s)\n \t\t\t\tused = rte_tel_json_add_array_u64(cb_data_buf,\n \t\t\t\t\t\tbuf_len, used,\n \t\t\t\t\t\td->data.array[i].u64val);\n+\t\t\telse if (d->type == RTE_TEL_ARRAY_CONTAINER) {\n+\t\t\t\tchar temp[buf_len];\n+\t\t\t\tconst struct container *rec_data =\n+\t\t\t\t\t\t&d->data.array[i].container;\n+\t\t\t\tif (container_to_json(rec_data->data,\n+\t\t\t\t\t\ttemp, buf_len) != 0)\n+\t\t\t\t\tused = rte_tel_json_add_array_json(\n+\t\t\t\t\t\t\tcb_data_buf,\n+\t\t\t\t\t\t\tbuf_len, used, temp);\n+\t\t\t\tif (!rec_data->keep)\n+\t\t\t\t\trte_tel_data_free(rec_data->data);\n+\t\t\t}\n \t\tused += prefix_used;\n \t\tused += strlcat(out_buf + used, \"}\", sizeof(out_buf) - used);\n \t\tbreak;\ndiff --git a/lib/librte_telemetry/telemetry_data.c b/lib/librte_telemetry/telemetry_data.c\nindex f424bbd48f..77b0fe09a5 100644\n--- a/lib/librte_telemetry/telemetry_data.c\n+++ b/lib/librte_telemetry/telemetry_data.c\n@@ -14,6 +14,7 @@ rte_tel_data_start_array(struct rte_tel_data *d, enum rte_tel_value_type type)\n \t\t\tRTE_TEL_ARRAY_STRING, /* RTE_TEL_STRING_VAL = 0 */\n \t\t\tRTE_TEL_ARRAY_INT,    /* RTE_TEL_INT_VAL = 1 */\n \t\t\tRTE_TEL_ARRAY_U64,    /* RTE_TEL_u64_VAL = 2 */\n+\t\t\tRTE_TEL_ARRAY_CONTAINER, /* RTE_TEL_CONTAINER = 3 */\n \t};\n \td->type = array_types[type];\n \td->data_len = 0;\n@@ -74,6 +75,23 @@ rte_tel_data_add_array_u64(struct rte_tel_data *d, uint64_t x)\n \treturn 0;\n }\n \n+int\n+rte_tel_data_add_array_container(struct rte_tel_data *d,\n+\t\tstruct rte_tel_data *val, int keep)\n+{\n+\tif (d->type != RTE_TEL_ARRAY_CONTAINER ||\n+\t\t\t(val->type != RTE_TEL_ARRAY_U64\n+\t\t\t&& val->type != RTE_TEL_ARRAY_INT\n+\t\t\t&& val->type != RTE_TEL_ARRAY_STRING))\n+\t\treturn -EINVAL;\n+\tif (d->data_len >= RTE_TEL_MAX_ARRAY_ENTRIES)\n+\t\treturn -ENOSPC;\n+\n+\td->data.array[d->data_len].container.data = val;\n+\td->data.array[d->data_len++].container.keep = !!keep;\n+\treturn 0;\n+}\n+\n int\n rte_tel_data_add_dict_string(struct rte_tel_data *d, const char *name,\n \t\tconst char *val)\n@@ -128,3 +146,36 @@ rte_tel_data_add_dict_u64(struct rte_tel_data *d,\n \tconst size_t bytes = strlcpy(e->name, name, RTE_TEL_MAX_STRING_LEN);\n \treturn bytes < RTE_TEL_MAX_STRING_LEN ? 0 : E2BIG;\n }\n+\n+int\n+rte_tel_data_add_dict_container(struct rte_tel_data *d, const char *name,\n+\t\tstruct rte_tel_data *val, int keep)\n+{\n+\tstruct tel_dict_entry *e = &d->data.dict[d->data_len];\n+\n+\tif (d->type != RTE_TEL_DICT || (val->type != RTE_TEL_ARRAY_U64\n+\t\t\t&& val->type != RTE_TEL_ARRAY_INT\n+\t\t\t&& val->type != RTE_TEL_ARRAY_STRING))\n+\t\treturn -EINVAL;\n+\tif (d->data_len >= RTE_TEL_MAX_DICT_ENTRIES)\n+\t\treturn -ENOSPC;\n+\n+\td->data_len++;\n+\te->type = RTE_TEL_CONTAINER;\n+\te->value.container.data = val;\n+\te->value.container.keep = !!keep;\n+\tconst size_t bytes = strlcpy(e->name, name, RTE_TEL_MAX_STRING_LEN);\n+\treturn bytes < RTE_TEL_MAX_STRING_LEN ? 0 : E2BIG;\n+}\n+\n+struct rte_tel_data *\n+rte_tel_data_alloc(void)\n+{\n+\treturn malloc(sizeof(struct rte_tel_data));\n+}\n+\n+void\n+rte_tel_data_free(struct rte_tel_data *data)\n+{\n+\tfree(data);\n+}\ndiff --git a/lib/librte_telemetry/telemetry_data.h b/lib/librte_telemetry/telemetry_data.h\nindex ff3a371a33..adb84a09f1 100644\n--- a/lib/librte_telemetry/telemetry_data.h\n+++ b/lib/librte_telemetry/telemetry_data.h\n@@ -15,6 +15,12 @@ enum tel_container_types {\n \tRTE_TEL_ARRAY_STRING, /** array of string values only */\n \tRTE_TEL_ARRAY_INT,    /** array of signed, 32-bit int values */\n \tRTE_TEL_ARRAY_U64,    /** array of unsigned 64-bit int values */\n+\tRTE_TEL_ARRAY_CONTAINER, /** array of container structs */\n+};\n+\n+struct container {\n+\tstruct rte_tel_data *data;\n+\tint keep;\n };\n \n /* each type here must have an equivalent enum in the value types enum in\n@@ -25,6 +31,7 @@ union tel_value {\n \tchar sval[RTE_TEL_MAX_STRING_LEN];\n \tint ival;\n \tuint64_t u64val;\n+\tstruct container container;\n };\n \n struct tel_dict_entry {\ndiff --git a/lib/librte_telemetry/telemetry_json.h b/lib/librte_telemetry/telemetry_json.h\nindex a2ce4899e0..ad270b9b30 100644\n--- a/lib/librte_telemetry/telemetry_json.h\n+++ b/lib/librte_telemetry/telemetry_json.h\n@@ -102,6 +102,22 @@ rte_tel_json_add_array_u64(char *buf, const int len, const int used,\n \treturn ret == 0 ? used : end + ret;\n }\n \n+/*\n+ * Add a new element with raw JSON value to the JSON array stored in the\n+ * provided buffer.\n+ */\n+static inline int\n+rte_tel_json_add_array_json(char *buf, const int len, const int used,\n+\t\tconst char *str)\n+{\n+\tint ret, end = used - 1; /* strip off final delimiter */\n+\tif (used <= 2) /* assume empty, since minimum is '[]' */\n+\t\treturn __json_snprintf(buf, len, \"[%s]\", str);\n+\n+\tret = __json_snprintf(buf + end, len - end, \",%s]\", str);\n+\treturn ret == 0 ? used : end + ret;\n+}\n+\n /**\n  * Add a new element with uint64_t value to the JSON object stored in the\n  * provided buffer.\n@@ -155,4 +171,21 @@ rte_tel_json_add_obj_str(char *buf, const int len, const int used,\n \treturn ret == 0 ? used : end + ret;\n }\n \n+/**\n+ * Add a new element with raw JSON value to the JSON object stored in the\n+ * provided buffer.\n+ */\n+static inline int\n+rte_tel_json_add_obj_json(char *buf, const int len, const int used,\n+\t\tconst char *name, const char *val)\n+{\n+\tint ret, end = used - 1;\n+\tif (used <= 2) /* assume empty, since minimum is '{}' */\n+\t\treturn __json_snprintf(buf, len, \"{\\\"%s\\\":%s}\", name, val);\n+\n+\tret = __json_snprintf(buf + end, len - end, \",\\\"%s\\\":%s}\",\n+\t\t\tname, val);\n+\treturn ret == 0 ? used : end + ret;\n+}\n+\n #endif /*_RTE_TELEMETRY_JSON_H_*/\n",
    "prefixes": [
        "v8",
        "1/3"
    ]
}