get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 47270,
    "url": "http://patchwork.dpdk.org/api/patches/47270/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/1540344746-29045-3-git-send-email-honnappa.nagarahalli@arm.com/",
    "project": {
        "id": 1,
        "url": "http://patchwork.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": "<1540344746-29045-3-git-send-email-honnappa.nagarahalli@arm.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1540344746-29045-3-git-send-email-honnappa.nagarahalli@arm.com",
    "date": "2018-10-24T01:32:23",
    "name": "[v6,2/5] hash: support do not free on delete",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "9fab8094189952eb6a511f513bf5b7e17ea743bb",
    "submitter": {
        "id": 1045,
        "url": "http://patchwork.dpdk.org/api/people/1045/?format=api",
        "name": "Honnappa Nagarahalli",
        "email": "honnappa.nagarahalli@arm.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patchwork.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/1540344746-29045-3-git-send-email-honnappa.nagarahalli@arm.com/mbox/",
    "series": [
        {
            "id": 2045,
            "url": "http://patchwork.dpdk.org/api/series/2045/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=2045",
            "date": "2018-10-24T01:32:21",
            "name": "Address reader-writer concurrency in rte_hash",
            "version": 6,
            "mbox": "http://patchwork.dpdk.org/series/2045/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/47270/comments/",
    "check": "success",
    "checks": "http://patchwork.dpdk.org/api/patches/47270/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 000F17CEB;\n\tWed, 24 Oct 2018 03:32:44 +0200 (CEST)",
            "from foss.arm.com (foss.arm.com [217.140.101.70])\n\tby dpdk.org (Postfix) with ESMTP id 773005B2A\n\tfor <dev@dpdk.org>; Wed, 24 Oct 2018 03:32:39 +0200 (CEST)",
            "from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249])\n\tby usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id A091D15AB;\n\tTue, 23 Oct 2018 18:32:38 -0700 (PDT)",
            "from 2p2660v4-1.austin.arm.com (2p2660v4-1.austin.arm.com\n\t[10.118.14.139])\n\tby usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id\n\t324F93F627; Tue, 23 Oct 2018 18:32:38 -0700 (PDT)"
        ],
        "From": "Honnappa Nagarahalli <honnappa.nagarahalli@arm.com>",
        "To": "bruce.richardson@intel.com,\n\tpablo.de.lara.guarch@intel.com",
        "Cc": "dev@dpdk.org, yipeng1.wang@intel.com, honnappa.nagarahalli@arm.com,\n\tdharmik.thakkar@arm.com, gavin.hu@arm.com, nd@arm.com",
        "Date": "Tue, 23 Oct 2018 20:32:23 -0500",
        "Message-Id": "<1540344746-29045-3-git-send-email-honnappa.nagarahalli@arm.com>",
        "X-Mailer": "git-send-email 2.7.4",
        "In-Reply-To": "<1540344746-29045-1-git-send-email-honnappa.nagarahalli@arm.com>",
        "References": "<1540344746-29045-1-git-send-email-honnappa.nagarahalli@arm.com>",
        "Subject": "[dpdk-dev] [PATCH v6 2/5] hash: support do not free on delete",
        "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\t<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\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "rte_hash_lookup_xxx APIs return the index of slot in\nthe key store. Application(reader) can use that index to reference\nother data structures in its scope. Because of this, the\nindex should not be freed till the application completes\nusing the index.\nRTE_HASH_EXTRA_FLAGS_NO_FREE_ON_DEL is introduced to support this.\nWhen this flag is enabled rte_hash_del_xxx APIs do not free the\nkey-store index/internal memory associated with the deleted\nentry. The new API rte_hash_free_key_with_position should be called\nto free the key-store index/internal memory after calling\nrte_hash_del_xxx APIs.\n\nSuggested-by: Yipeng Wang <yipeng1.wang@intel.com>\nSigned-off-by: Honnappa Nagarahalli <honnappa.nagarahalli@arm.com>\nReviewed-by: Gavin Hu <gavin.hu@arm.com>\nReviewed-by: Yipeng Wang <yipeng1.wang@intel.com>\nAcked-by: Bruce Richardson <bruce.richardson@intel.com>\n---\n lib/librte_hash/rte_cuckoo_hash.c |  50 +++++++++++++-\n lib/librte_hash/rte_cuckoo_hash.h |   6 ++\n lib/librte_hash/rte_hash.h        |  40 +++++++++++\n test/test/test_hash.c             | 140 +++++++++++++++++++++++++++++++++++++-\n 4 files changed, 232 insertions(+), 4 deletions(-)",
    "diff": "diff --git a/lib/librte_hash/rte_cuckoo_hash.c b/lib/librte_hash/rte_cuckoo_hash.c\nindex 3539a10..e087393 100644\n--- a/lib/librte_hash/rte_cuckoo_hash.c\n+++ b/lib/librte_hash/rte_cuckoo_hash.c\n@@ -140,6 +140,7 @@ rte_hash_create(const struct rte_hash_parameters *params)\n \tunsigned int ext_table_support = 0;\n \tunsigned int readwrite_concur_support = 0;\n \tunsigned int writer_takes_lock = 0;\n+\tunsigned int no_free_on_del = 0;\n \n \trte_hash_function default_hash_func = (rte_hash_function)rte_jhash;\n \n@@ -176,6 +177,9 @@ rte_hash_create(const struct rte_hash_parameters *params)\n \tif (params->extra_flag & RTE_HASH_EXTRA_FLAGS_EXT_TABLE)\n \t\text_table_support = 1;\n \n+\tif (params->extra_flag & RTE_HASH_EXTRA_FLAGS_NO_FREE_ON_DEL)\n+\t\tno_free_on_del = 1;\n+\n \t/* Store all keys and leave the first entry as a dummy entry for lookup_bulk */\n \tif (use_local_cache)\n \t\t/*\n@@ -359,6 +363,7 @@ rte_hash_create(const struct rte_hash_parameters *params)\n \th->readwrite_concur_support = readwrite_concur_support;\n \th->ext_table_support = ext_table_support;\n \th->writer_takes_lock = writer_takes_lock;\n+\th->no_free_on_del = no_free_on_del;\n \n #if defined(RTE_ARCH_X86)\n \tif (rte_cpu_get_flag_enabled(RTE_CPUFLAG_SSE2))\n@@ -1121,7 +1126,6 @@ remove_entry(const struct rte_hash *h, struct rte_hash_bucket *bkt, unsigned i)\n \tunsigned lcore_id, n_slots;\n \tstruct lcore_cache *cached_free_slots;\n \n-\tbkt->sig_current[i] = NULL_SIGNATURE;\n \tif (h->use_local_cache) {\n \t\tlcore_id = rte_lcore_id();\n \t\tcached_free_slots = &h->local_free_slots[lcore_id];\n@@ -1183,7 +1187,12 @@ search_and_remove(const struct rte_hash *h, const void *key,\n \t\t\tk = (struct rte_hash_key *) ((char *)keys +\n \t\t\t\t\tbkt->key_idx[i] * h->key_entry_size);\n \t\t\tif (rte_hash_cmp_eq(key, k->key, h) == 0) {\n-\t\t\t\tremove_entry(h, bkt, i);\n+\t\t\t\tbkt->sig_current[i] = NULL_SIGNATURE;\n+\t\t\t\t/* Free the key store index if\n+\t\t\t\t * no_free_on_del is disabled.\n+\t\t\t\t */\n+\t\t\t\tif (!h->no_free_on_del)\n+\t\t\t\t\tremove_entry(h, bkt, i);\n \n \t\t\t\t/* Return index where key is stored,\n \t\t\t\t * subtracting the first dummy index\n@@ -1301,6 +1310,43 @@ rte_hash_get_key_with_position(const struct rte_hash *h, const int32_t position,\n \treturn 0;\n }\n \n+int __rte_experimental\n+rte_hash_free_key_with_position(const struct rte_hash *h,\n+\t\t\t\tconst int32_t position)\n+{\n+\tRETURN_IF_TRUE(((h == NULL) || (position == EMPTY_SLOT)), -EINVAL);\n+\n+\tunsigned int lcore_id, n_slots;\n+\tstruct lcore_cache *cached_free_slots;\n+\tconst int32_t total_entries = h->num_buckets * RTE_HASH_BUCKET_ENTRIES;\n+\n+\t/* Out of bounds */\n+\tif (position >= total_entries)\n+\t\treturn -EINVAL;\n+\n+\tif (h->use_local_cache) {\n+\t\tlcore_id = rte_lcore_id();\n+\t\tcached_free_slots = &h->local_free_slots[lcore_id];\n+\t\t/* Cache full, need to free it. */\n+\t\tif (cached_free_slots->len == LCORE_CACHE_SIZE) {\n+\t\t\t/* Need to enqueue the free slots in global ring. */\n+\t\t\tn_slots = rte_ring_mp_enqueue_burst(h->free_slots,\n+\t\t\t\t\t\tcached_free_slots->objs,\n+\t\t\t\t\t\tLCORE_CACHE_SIZE, NULL);\n+\t\t\tcached_free_slots->len -= n_slots;\n+\t\t}\n+\t\t/* Put index of new free slot in cache. */\n+\t\tcached_free_slots->objs[cached_free_slots->len] =\n+\t\t\t\t\t(void *)((uintptr_t)position);\n+\t\tcached_free_slots->len++;\n+\t} else {\n+\t\trte_ring_sp_enqueue(h->free_slots,\n+\t\t\t\t(void *)((uintptr_t)position));\n+\t}\n+\n+\treturn 0;\n+}\n+\n static inline void\n compare_signatures(uint32_t *prim_hash_matches, uint32_t *sec_hash_matches,\n \t\t\tconst struct rte_hash_bucket *prim_bkt,\ndiff --git a/lib/librte_hash/rte_cuckoo_hash.h b/lib/librte_hash/rte_cuckoo_hash.h\nindex 8c522ac..ff95181 100644\n--- a/lib/librte_hash/rte_cuckoo_hash.h\n+++ b/lib/librte_hash/rte_cuckoo_hash.h\n@@ -168,6 +168,12 @@ struct rte_hash {\n \tuint8_t readwrite_concur_support;\n \t/**< If read-write concurrency support is enabled */\n \tuint8_t ext_table_support;     /**< Enable extendable bucket table */\n+\tuint8_t no_free_on_del;\n+\t/**< If key index should be freed on calling rte_hash_del_xxx APIs.\n+\t * If this is set, rte_hash_free_key_with_position must be called to\n+\t * free the key index associated with the deleted entry.\n+\t * This flag is enabled by default.\n+\t */\n \tuint8_t writer_takes_lock;\n \t/**< Indicates if the writer threads need to take lock */\n \trte_hash_function hash_func;    /**< Function used to calculate hash. */\ndiff --git a/lib/librte_hash/rte_hash.h b/lib/librte_hash/rte_hash.h\nindex 6ace64e..dfa542b 100644\n--- a/lib/librte_hash/rte_hash.h\n+++ b/lib/librte_hash/rte_hash.h\n@@ -14,6 +14,8 @@\n #include <stdint.h>\n #include <stddef.h>\n \n+#include <rte_compat.h>\n+\n #ifdef __cplusplus\n extern \"C\" {\n #endif\n@@ -40,6 +42,11 @@ extern \"C\" {\n /** Flag to indicate the extendabe bucket table feature should be used */\n #define RTE_HASH_EXTRA_FLAGS_EXT_TABLE 0x08\n \n+/** Flag to disable freeing of key index on hash delete.\n+ * Refer to rte_hash_del_xxx APIs for more details.\n+ */\n+#define RTE_HASH_EXTRA_FLAGS_NO_FREE_ON_DEL 0x10\n+\n /**\n  * The type of hash value of a key.\n  * It should be a value of at least 32bit with fully random pattern.\n@@ -236,6 +243,10 @@ rte_hash_add_key_with_hash(const struct rte_hash *h, const void *key, hash_sig_t\n  * and should only be called from one thread by default.\n  * Thread safety can be enabled by setting flag during\n  * table creation.\n+ * If RTE_HASH_EXTRA_FLAGS_NO_FREE_ON_DEL is enabled,\n+ * the key index returned by rte_hash_add_key_xxx APIs will not be\n+ * freed by this API. rte_hash_free_key_with_position API must be called\n+ * additionally to free the index associated with the key.\n  *\n  * @param h\n  *   Hash table to remove the key from.\n@@ -257,6 +268,10 @@ rte_hash_del_key(const struct rte_hash *h, const void *key);\n  * and should only be called from one thread by default.\n  * Thread safety can be enabled by setting flag during\n  * table creation.\n+ * If RTE_HASH_EXTRA_FLAGS_NO_FREE_ON_DEL is enabled,\n+ * the key index returned by rte_hash_add_key_xxx APIs will not be\n+ * freed by this API. rte_hash_free_key_with_position API must be called\n+ * additionally to free the index associated with the key.\n  *\n  * @param h\n  *   Hash table to remove the key from.\n@@ -296,6 +311,31 @@ rte_hash_get_key_with_position(const struct rte_hash *h, const int32_t position,\n \t\t\t       void **key);\n \n /**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice\n+ *\n+ * Free a hash key in the hash table given the position\n+ * of the key. This operation is not multi-thread safe and should\n+ * only be called from one thread by default. Thread safety\n+ * can be enabled by setting flag during table creation.\n+ * If RTE_HASH_EXTRA_FLAGS_NO_FREE_ON_DEL is enabled,\n+ * this API must be called, with the key index returned by rte_hash_add_key_xxx\n+ * APIs, after the key is deleted using rte_hash_del_key_xxx APIs.\n+ * This API does not validate if the key is already freed.\n+ *\n+ * @param h\n+ *   Hash table to free the key from.\n+ * @param position\n+ *   Position returned when the key was deleted.\n+ * @return\n+ *   - 0 if freed successfully\n+ *   - -EINVAL if the parameters are invalid.\n+ */\n+int __rte_experimental\n+rte_hash_free_key_with_position(const struct rte_hash *h,\n+\t\t\t\tconst int32_t position);\n+\n+/**\n  * Find a key-value pair in the hash table.\n  * This operation is multi-thread safe with regarding to other lookup threads.\n  * Read-write concurrency can be enabled by setting flag during\ndiff --git a/test/test/test_hash.c b/test/test/test_hash.c\nindex 815c734..6d06eb2 100644\n--- a/test/test/test_hash.c\n+++ b/test/test/test_hash.c\n@@ -260,6 +260,13 @@ static void run_hash_func_tests(void)\n  *\t- lookup (hit)\n  *\t- delete\n  *\t- lookup (miss)\n+ *\n+ * Repeat the test case when 'free on delete' is disabled.\n+ *\t- add\n+ *\t- lookup (hit)\n+ *\t- delete\n+ *\t- lookup (miss)\n+ *\t- free\n  */\n static int test_add_delete(void)\n {\n@@ -295,10 +302,12 @@ static int test_add_delete(void)\n \n \t/* repeat test with precomputed hash functions */\n \thash_sig_t hash_value;\n-\tint pos1, expectedPos1;\n+\tint pos1, expectedPos1, delPos1;\n \n+\tut_params.extra_flag = RTE_HASH_EXTRA_FLAGS_NO_FREE_ON_DEL;\n \thandle = rte_hash_create(&ut_params);\n \tRETURN_IF_ERROR(handle == NULL, \"hash creation failed\");\n+\tut_params.extra_flag = 0;\n \n \thash_value = rte_hash_hash(handle, &keys[0]);\n \tpos1 = rte_hash_add_key_with_hash(handle, &keys[0], hash_value);\n@@ -315,12 +324,18 @@ static int test_add_delete(void)\n \tprint_key_info(\"Del\", &keys[0], pos1);\n \tRETURN_IF_ERROR(pos1 != expectedPos1,\n \t\t\t\"failed to delete key (pos1=%d)\", pos1);\n+\tdelPos1 = pos1;\n \n \tpos1 = rte_hash_lookup_with_hash(handle, &keys[0], hash_value);\n \tprint_key_info(\"Lkp\", &keys[0], pos1);\n \tRETURN_IF_ERROR(pos1 != -ENOENT,\n \t\t\t\"fail: found key after deleting! (pos1=%d)\", pos1);\n \n+\tpos1 = rte_hash_free_key_with_position(handle, delPos1);\n+\tprint_key_info(\"Free\", &keys[0], delPos1);\n+\tRETURN_IF_ERROR(pos1 != 0,\n+\t\t\t\"failed to free key (pos1=%d)\", delPos1);\n+\n \trte_hash_free(handle);\n \n \treturn 0;\n@@ -391,6 +406,84 @@ static int test_add_update_delete(void)\n }\n \n /*\n+ * Sequence of operations for a single key with 'disable free on del' set:\n+ *\t- delete: miss\n+ *\t- add\n+ *\t- lookup: hit\n+ *\t- add: update\n+ *\t- lookup: hit (updated data)\n+ *\t- delete: hit\n+ *\t- delete: miss\n+ *\t- lookup: miss\n+ *\t- free: hit\n+ *\t- lookup: miss\n+ */\n+static int test_add_update_delete_free(void)\n+{\n+\tstruct rte_hash *handle;\n+\tint pos0, expectedPos0, delPos0, result;\n+\n+\tut_params.name = \"test2\";\n+\tut_params.extra_flag = RTE_HASH_EXTRA_FLAGS_NO_FREE_ON_DEL;\n+\thandle = rte_hash_create(&ut_params);\n+\tRETURN_IF_ERROR(handle == NULL, \"hash creation failed\");\n+\tut_params.extra_flag = 0;\n+\n+\tpos0 = rte_hash_del_key(handle, &keys[0]);\n+\tprint_key_info(\"Del\", &keys[0], pos0);\n+\tRETURN_IF_ERROR(pos0 != -ENOENT,\n+\t\t\t\"fail: found non-existent key (pos0=%d)\", pos0);\n+\n+\tpos0 = rte_hash_add_key(handle, &keys[0]);\n+\tprint_key_info(\"Add\", &keys[0], pos0);\n+\tRETURN_IF_ERROR(pos0 < 0, \"failed to add key (pos0=%d)\", pos0);\n+\texpectedPos0 = pos0;\n+\n+\tpos0 = rte_hash_lookup(handle, &keys[0]);\n+\tprint_key_info(\"Lkp\", &keys[0], pos0);\n+\tRETURN_IF_ERROR(pos0 != expectedPos0,\n+\t\t\t\"failed to find key (pos0=%d)\", pos0);\n+\n+\tpos0 = rte_hash_add_key(handle, &keys[0]);\n+\tprint_key_info(\"Add\", &keys[0], pos0);\n+\tRETURN_IF_ERROR(pos0 != expectedPos0,\n+\t\t\t\"failed to re-add key (pos0=%d)\", pos0);\n+\n+\tpos0 = rte_hash_lookup(handle, &keys[0]);\n+\tprint_key_info(\"Lkp\", &keys[0], pos0);\n+\tRETURN_IF_ERROR(pos0 != expectedPos0,\n+\t\t\t\"failed to find key (pos0=%d)\", pos0);\n+\n+\tdelPos0 = rte_hash_del_key(handle, &keys[0]);\n+\tprint_key_info(\"Del\", &keys[0], delPos0);\n+\tRETURN_IF_ERROR(delPos0 != expectedPos0,\n+\t\t\t\"failed to delete key (pos0=%d)\", delPos0);\n+\n+\tpos0 = rte_hash_del_key(handle, &keys[0]);\n+\tprint_key_info(\"Del\", &keys[0], pos0);\n+\tRETURN_IF_ERROR(pos0 != -ENOENT,\n+\t\t\t\"fail: deleted already deleted key (pos0=%d)\", pos0);\n+\n+\tpos0 = rte_hash_lookup(handle, &keys[0]);\n+\tprint_key_info(\"Lkp\", &keys[0], pos0);\n+\tRETURN_IF_ERROR(pos0 != -ENOENT,\n+\t\t\t\"fail: found key after deleting! (pos0=%d)\", pos0);\n+\n+\tresult = rte_hash_free_key_with_position(handle, delPos0);\n+\tprint_key_info(\"Free\", &keys[0], delPos0);\n+\tRETURN_IF_ERROR(result != 0,\n+\t\t\t\"failed to free key (pos1=%d)\", delPos0);\n+\n+\tpos0 = rte_hash_lookup(handle, &keys[0]);\n+\tprint_key_info(\"Lkp\", &keys[0], pos0);\n+\tRETURN_IF_ERROR(pos0 != -ENOENT,\n+\t\t\t\"fail: found key after deleting! (pos0=%d)\", pos0);\n+\n+\trte_hash_free(handle);\n+\treturn 0;\n+}\n+\n+/*\n  * Sequence of operations for retrieving a key with its position\n  *\n  *  - create table\n@@ -399,11 +492,20 @@ static int test_add_update_delete(void)\n  *  - delete key\n  *  - try to get the deleted key: miss\n  *\n+ * Repeat the test case when 'free on delete' is disabled.\n+ *  - create table\n+ *  - add key\n+ *  - get the key with its position: hit\n+ *  - delete key\n+ *  - try to get the deleted key: hit\n+ *  - free key\n+ *  - try to get the deleted key: miss\n+ *\n  */\n static int test_hash_get_key_with_position(void)\n {\n \tstruct rte_hash *handle = NULL;\n-\tint pos, expectedPos, result;\n+\tint pos, expectedPos, delPos, result;\n \tvoid *key;\n \n \tut_params.name = \"hash_get_key_w_pos\";\n@@ -427,6 +529,38 @@ static int test_hash_get_key_with_position(void)\n \tRETURN_IF_ERROR(result != -ENOENT, \"non valid key retrieved\");\n \n \trte_hash_free(handle);\n+\n+\tut_params.name = \"hash_get_key_w_pos\";\n+\tut_params.extra_flag = RTE_HASH_EXTRA_FLAGS_NO_FREE_ON_DEL;\n+\thandle = rte_hash_create(&ut_params);\n+\tRETURN_IF_ERROR(handle == NULL, \"hash creation failed\");\n+\tut_params.extra_flag = 0;\n+\n+\tpos = rte_hash_add_key(handle, &keys[0]);\n+\tprint_key_info(\"Add\", &keys[0], pos);\n+\tRETURN_IF_ERROR(pos < 0, \"failed to add key (pos0=%d)\", pos);\n+\texpectedPos = pos;\n+\n+\tresult = rte_hash_get_key_with_position(handle, pos, &key);\n+\tRETURN_IF_ERROR(result != 0, \"error retrieving a key\");\n+\n+\tdelPos = rte_hash_del_key(handle, &keys[0]);\n+\tprint_key_info(\"Del\", &keys[0], delPos);\n+\tRETURN_IF_ERROR(delPos != expectedPos,\n+\t\t\t\"failed to delete key (pos0=%d)\", delPos);\n+\n+\tresult = rte_hash_get_key_with_position(handle, delPos, &key);\n+\tRETURN_IF_ERROR(result != -ENOENT, \"non valid key retrieved\");\n+\n+\tresult = rte_hash_free_key_with_position(handle, delPos);\n+\tprint_key_info(\"Free\", &keys[0], delPos);\n+\tRETURN_IF_ERROR(result != 0,\n+\t\t\t\"failed to free key (pos1=%d)\", delPos);\n+\n+\tresult = rte_hash_get_key_with_position(handle, delPos, &key);\n+\tRETURN_IF_ERROR(result != -ENOENT, \"non valid key retrieved\");\n+\n+\trte_hash_free(handle);\n \treturn 0;\n }\n \n@@ -1609,6 +1743,8 @@ test_hash(void)\n \t\treturn -1;\n \tif (test_add_update_delete() < 0)\n \t\treturn -1;\n+\tif (test_add_update_delete_free() < 0)\n+\t\treturn -1;\n \tif (test_five_keys() < 0)\n \t\treturn -1;\n \tif (test_full_bucket() < 0)\n",
    "prefixes": [
        "v6",
        "2/5"
    ]
}