Performance improvements and override mandatory to optional rules
Change-Id: Id099f1f03443fafce2f2181e305fbababbe0fa1f
diff --git a/libfdproto/CMakeLists.txt b/libfdproto/CMakeLists.txt
index 3650719..415825d 100644
--- a/libfdproto/CMakeLists.txt
+++ b/libfdproto/CMakeLists.txt
@@ -7,6 +7,8 @@
cmake_policy(SET CMP0022 OLD)
endif (POLICY CMP0022)
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+
# List of source files for the library
SET(LFDPROTO_SRC
fdproto-internal.h
@@ -24,6 +26,7 @@
sessions.c
utils.c
version.c
+ hashlist.cpp
)
diff --git a/libfdproto/dictionary.c b/libfdproto/dictionary.c
index ff902a0..daf7066 100644
--- a/libfdproto/dictionary.c
+++ b/libfdproto/dictionary.c
@@ -36,6 +36,53 @@
#include "fdproto-internal.h"
#include <inttypes.h>
+#define ENABLE_LOCK_BYPASS 1
+#define USE_HASHLIST 1
+
+#if USE_HASHLIST
+ int initInt32HashList(void **hl);
+ void deleteInt32HashList(void *hl);
+ void deleteEntryInt32HashList(int32_t k, void *hl);
+ int insertInt32HashList(int32_t k, void *v, void *hl, void **duplicate);
+ int findInt32HashList(int32_t k, void *hl, void **result);
+
+ int initInt64HashList(void **hl);
+ void deleteInt64HashList(void *hl);
+ void deleteEntryInt64HashList(int64_t k, void *hl);
+ int insertInt64HashList(int64_t k, void *v, void *hl, void **duplicate);
+ int findInt64HashList(int64_t k, void *hl, void **result);
+
+ int initUInt32HashList(void **hl);
+ void deleteUInt32HashList(void *hl);
+ void deleteEntryUInt32HashList(uint32_t k, void *hl);
+ int insertUInt32HashList(uint32_t k, void *v, void *hl, void **duplicate);
+ int findUInt32HashList(uint32_t k, void *hl, void **result);
+
+ int initUInt64HashList(void **hl);
+ void deleteUInt64HashList(void *hl);
+ void deleteEntryUInt64HashList(uint64_t k, void *hl);
+ int insertUInt64HashList(uint64_t k, void *v, void *hl, void **duplicate);
+ int findUInt64HashList(uint64_t k, void *hl, void **result);
+
+ int initFloat32HashList(void **hl);
+ void deleteFloat32HashList(void *hl);
+ void deleteEntryFloat32HashList(float k, void *hl);
+ int insertFloat32HashList(float k, void *v, void *hl, void **duplicate);
+ int findFloat32HashList(float k, void *hl, void **result);
+
+ int initFloat64HashList(void **hl);
+ void deleteFloat64HashList(void *hl);
+ void deleteEntryFloat64HashList(double k, void *hl);
+ int insertFloat64HashList(double k, void *v, void *hl, void **duplicate);
+ int findFloat64HashList(double k, void *hl, void **result);
+
+ int initStringHashList(void **hl);
+ void deleteStringHashList(void *hl);
+ void deleteEntryStringHashList(const char *k, void *hl);
+ int insertStringHashList(const char *k, void *v, void *hl, void **duplicate);
+ int findStringHashList(const char *k, void *hl, void **result);
+#endif
+
/* Names of the base types */
const char * type_base_name[] = { /* must keep in sync with dict_avp_basetype */
"GROUPED", /* AVP_TYPE_GROUPED */
@@ -77,6 +124,10 @@
struct dict_object * parent; /* The parent of this object, if any */
struct fd_list list[NB_LISTS_PER_OBJ];/* used to chain objects.*/
+#ifdef USE_HASHLIST
+ void * hashlist[NB_LISTS_PER_OBJ];
+#endif
+
/* More information about the lists :
- the use for each list depends on the type of object. See detail below.
@@ -133,6 +184,9 @@
struct dictionary {
int dict_eyec; /* Eye-catcher for the dictionary (DICT_EYECATCHER) */
+#if ENABLE_LOCK_BYPASS
+ int dict_bypass_lock; /* When true, don't use the dict_lock */
+#endif
pthread_rwlock_t dict_lock; /* The global rwlock for the dictionary */
struct dict_object dict_vendors; /* Sentinel for the list of vendors, corresponding to vendor 0 */
@@ -274,6 +328,10 @@
switch (type) {
case DICT_VENDOR:
DUP_string_len( dest->data.vendor.vendor_name, &dest->datastr_len );
+#if USE_HASHLIST
+ initUInt32HashList(&dest->hashlist[0]);
+ initStringHashList(&dest->hashlist[1]);
+#endif
break;
case DICT_APPLICATION:
@@ -282,6 +340,35 @@
case DICT_TYPE:
DUP_string_len( dest->data.type.type_name, &dest->datastr_len );
+#if USE_HASHLIST
+ switch (dest->data.type.type_base)
+ {
+ case AVP_TYPE_OCTETSTRING:
+ break;
+ case AVP_TYPE_INTEGER32:
+ initInt32HashList(&dest->hashlist[0]);
+ break;
+ case AVP_TYPE_INTEGER64:
+ initInt64HashList(&dest->hashlist[0]);
+ break;
+ case AVP_TYPE_UNSIGNED32:
+ initUInt32HashList(&dest->hashlist[0]);
+ break;
+ case AVP_TYPE_UNSIGNED64:
+ initUInt64HashList(&dest->hashlist[0]);
+ break;
+ case AVP_TYPE_FLOAT32:
+ initFloat32HashList(&dest->hashlist[0]);
+ break;
+ case AVP_TYPE_FLOAT64:
+ initFloat64HashList(&dest->hashlist[0]);
+ break;
+ case AVP_TYPE_GROUPED:
+ default:
+ break;
+ }
+ initStringHashList(&dest->hashlist[1]);
+#endif
break;
case DICT_ENUMVAL:
@@ -346,6 +433,10 @@
switch (obj->type) {
case DICT_VENDOR:
free( obj->data.vendor.vendor_name );
+#if USE_HASHLIST
+ deleteUInt32HashList(obj->hashlist[0]);
+ deleteStringHashList(obj->hashlist[1]);
+#endif
break;
case DICT_APPLICATION:
@@ -354,6 +445,37 @@
case DICT_TYPE:
free( obj->data.type.type_name );
+#if USE_HASHLIST
+ switch (obj->data.type.type_base)
+ {
+ case AVP_TYPE_OCTETSTRING:
+ break;
+ case AVP_TYPE_INTEGER32:
+ deleteInt32HashList(obj->hashlist[0]);
+ break;
+ case AVP_TYPE_INTEGER64:
+ deleteInt64HashList(obj->hashlist[0]);
+ break;
+ case AVP_TYPE_UNSIGNED32:
+ deleteUInt32HashList(obj->hashlist[0]);
+ break;
+ case AVP_TYPE_UNSIGNED64:
+ deleteUInt64HashList(obj->hashlist[0]);
+ break;
+ case AVP_TYPE_FLOAT32:
+ deleteFloat32HashList(obj->hashlist[0]);
+ break;
+ case AVP_TYPE_FLOAT64:
+ deleteFloat64HashList(obj
+
+
+ ->hashlist[0]);
+ break;
+ default:
+ break;
+ }
+ deleteStringHashList(obj->hashlist[1]);
+#endif
break;
case DICT_ENUMVAL:
@@ -870,8 +992,12 @@
/* From here the "parent" object is valid */
if ( _what->search.enum_name != NULL ) {
+#if USE_HASHLIST
+ ret = findStringHashList(_what->search.enum_name, parent->hashlist[1], (void**)result);
+#else
/* We are looking for this string */
SEARCH_os0( _what->search.enum_name, &parent->list[1], enumval.enum_name, 1 );
+#endif
} else {
/* We are looking for the value in enum_value */
switch (parent->data.type.type_base) {
@@ -884,51 +1010,75 @@
break;
case AVP_TYPE_INTEGER32:
+#if USE_HASHLIST
+ ret = findInt32HashList(_what->search.enum_value.i32, parent->hashlist[0], (void**)result);
+#else
SEARCH_scalar( _what->search.enum_value.i32,
&parent->list[2],
enumval.enum_value.i32,
1,
(struct dict_object *)NULL);
+#endif
break;
case AVP_TYPE_INTEGER64:
+#if USE_HASHLIST
+ ret = findInt64HashList(_what->search.enum_value.i64, parent->hashlist[0], (void**)result);
+#else
SEARCH_scalar( _what->search.enum_value.i64,
&parent->list[2],
enumval.enum_value.i64,
1,
(struct dict_object *)NULL);
+#endif
break;
case AVP_TYPE_UNSIGNED32:
+#if USE_HASHLIST
+ ret = findUInt32HashList(_what->search.enum_value.u32, parent->hashlist[0], (void**)result);
+#else
SEARCH_scalar( _what->search.enum_value.u32,
&parent->list[2],
enumval.enum_value.u32,
1,
(struct dict_object *)NULL);
+#endif
break;
case AVP_TYPE_UNSIGNED64:
+#if USE_HASHLIST
+ ret = findUInt64HashList(_what->search.enum_value.u64, parent->hashlist[0], (void**)result);
+#else
SEARCH_scalar( _what->search.enum_value.u64,
&parent->list[2],
enumval.enum_value.u64,
1,
(struct dict_object *)NULL);
+#endif
break;
case AVP_TYPE_FLOAT32:
+#if USE_HASHLIST
+ ret = findFloat32HashList(_what->search.enum_value.f32, parent->hashlist[0], (void**)result);
+#else
SEARCH_scalar( _what->search.enum_value.f32,
&parent->list[2],
enumval.enum_value.f32,
1,
(struct dict_object *)NULL);
+#endif
break;
case AVP_TYPE_FLOAT64:
+#if USE_HASHLIST
+ ret = findFloat64HashList(_what->search.enum_value.f64, parent->hashlist[0], (void**)result);
+#else
SEARCH_scalar( _what->search.enum_value.f64,
&parent->list[2],
enumval.enum_value.f64,
1,
(struct dict_object *)NULL);
+#endif
break;
default:
@@ -961,13 +1111,21 @@
avp_code_t code;
code = *(avp_code_t *) what;
+#if USE_HASHLIST
+ ret = findUInt32HashList(code, dict->dict_vendors.hashlist[0], (void**)result);
+#else
SEARCH_scalar( code, &dict->dict_vendors.list[1], avp.avp_code, 1, (struct dict_object *)NULL );
+#endif
}
break;
case AVP_BY_NAME:
/* "what" is the AVP name, vendor 0 */
+#if USE_HASHLIST
+ ret = findStringHashList((const char *)what, dict->dict_vendors.hashlist[1], (void**)result);
+#else
SEARCH_os0( what, &dict->dict_vendors.list[2], avp.avp_name, 1);
+#endif
break;
case AVP_BY_CODE_AND_VENDOR:
@@ -990,10 +1148,18 @@
/* We now have our vendor = head of the appropriate avp list */
if (criteria == AVP_BY_NAME_AND_VENDOR) {
+#if USE_HASHLIST
+ ret = findStringHashList(_what->avp_name, vendor->hashlist[1], (void**)result);
+#else
SEARCH_os0( _what->avp_name, &vendor->list[2], avp.avp_name, 1);
+#endif
} else {
/* AVP_BY_CODE_AND_VENDOR */
+#if USE_HASHLIST
+ ret = findUInt32HashList(_what->avp_code, vendor->hashlist[0], (void**)result);
+#else
SEARCH_scalar( _what->avp_code, &vendor->list[1], avp.avp_code, 1, (struct dict_object *)NULL );
+#endif
}
}
break;
@@ -1028,9 +1194,17 @@
/* We now have our vendor = head of the appropriate avp list */
if (_what->avp_data.avp_code) {
CHECK_PARAMS( ! _what->avp_data.avp_name );
+#if USE_HASHLIST
+ ret = findUInt32HashList(_what->avp_data.avp_code, vendor->hashlist[0], (void**)result);
+#else
SEARCH_scalar( _what->avp_data.avp_code, &vendor->list[1], avp.avp_code, 1, (struct dict_object *)NULL );
+#endif
} else {
+#if USE_HASHLIST
+ ret = findStringHashList(_what->avp_data.avp_name, vendor->hashlist[1], (void**)result);
+#else
SEARCH_os0( _what->avp_data.avp_name, &vendor->list[2], avp.avp_name, 1);
+#endif
}
}
break;
@@ -1045,7 +1219,13 @@
/* If not found, loop for all vendors, until found */
for (li = dict->dict_vendors.list[0].next; li != &dict->dict_vendors.list[0]; li = li->next) {
+#if USE_HASHLIST
+ ret = findStringHashList(what, _O(li->o)->hashlist[1], (void**)result);
+ if (ret == 0 && *result)
+ goto end;
+#else
SEARCH_os0_l( what, wl, &_O(li->o)->list[2], avp.avp_name, 1);
+#endif
}
}
break;
@@ -1346,6 +1526,9 @@
return fd_dump_extend(FD_DUMP_STD_PARAMS, "INVALID/NULL");
}
+#if ENABLE_LOCK_BYPASS
+ if (!dict->dict_bypass_lock)
+#endif
CHECK_POSIX_DO( pthread_rwlock_rdlock( &dict->dict_lock ), /* ignore */ );
CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict(%p) : VENDORS / AVP / RULES}\n", dict), goto error);
@@ -1372,10 +1555,16 @@
for (i=1; i<=DICT_TYPE_MAX; i++)
CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n %5d: %s", dict->dict_count[i], dict_obj_info[i].name), goto error);
+#if ENABLE_LOCK_BYPASS
+ if (!dict->dict_bypass_lock)
+#endif
CHECK_POSIX_DO( pthread_rwlock_unlock( &dict->dict_lock ), /* ignore */ );
return *buf;
error:
/* Free the rwlock */
+#if ENABLE_LOCK_BYPASS
+ if (!dict->dict_bypass_lock)
+#endif
CHECK_POSIX_DO( pthread_rwlock_unlock( &dict->dict_lock ), /* ignore */ );
return NULL;
}
@@ -1682,11 +1871,14 @@
/* Initialize the data of the new object */
init_object(new, type);
+ new->dico = dict;
+ new->parent = parent;
init_object_data(new, data, type, dupos);
- new->dico = dict;
- new->parent = parent;
-
+
/* We will change the dictionary => acquire the write lock */
+#if ENABLE_LOCK_BYPASS
+ if (!dict->dict_bypass_lock)
+#endif
CHECK_POSIX_DO( ret = pthread_rwlock_wrlock(&dict->dict_lock), goto error_free );
/* Now link the object -- this also checks that no object with same keys already exists */
@@ -1713,6 +1905,75 @@
break;
case DICT_ENUMVAL:
+#if USE_HASHLIST
+ switch (parent->data.type.type_base)
+ {
+ case AVP_TYPE_INTEGER32:
+ ret = insertInt32HashList(new->data.enumval.enum_value.i32, new, parent->hashlist[0], (void**)&locref);
+ break;
+
+ case AVP_TYPE_INTEGER64:
+ ret = insertInt64HashList(new->data.enumval.enum_value.i64, new, parent->hashlist[0], (void**)&locref);
+ break;
+
+ case AVP_TYPE_UNSIGNED32:
+ ret = insertUInt32HashList(new->data.enumval.enum_value.u32, new, parent->hashlist[0], (void**)&locref);
+ break;
+
+ case AVP_TYPE_UNSIGNED64:
+ ret = insertUInt64HashList(new->data.enumval.enum_value.u64, new, parent->hashlist[0], (void**)&locref);
+ break;
+
+ case AVP_TYPE_FLOAT32:
+ ret = insertFloat32HashList(new->data.enumval.enum_value.f32, new, parent->hashlist[0], (void**)&locref);
+ break;
+
+ case AVP_TYPE_FLOAT64:
+ ret = insertFloat64HashList(new->data.enumval.enum_value.f64, new, parent->hashlist[0], (void**)&locref);
+ break;
+
+ default:
+ /* Invalid parent type basetype */
+ CHECK_PARAMS( parent = NULL );
+ }
+ if (ret)
+ goto error_unlock;
+
+ ret = insertStringHashList(new->data.enumval.enum_name, new, parent->hashlist[1], (void **)&locref);
+ if (ret) {
+ switch (parent->data.type.type_base)
+ {
+ case AVP_TYPE_INTEGER32:
+ deleteEntryInt32HashList(new->data.enumval.enum_value.i32, parent->hashlist[0]);
+ break;
+
+ case AVP_TYPE_INTEGER64:
+ deleteEntryInt64HashList(new->data.enumval.enum_value.i64, parent->hashlist[0]);
+ break;
+
+ case AVP_TYPE_UNSIGNED32:
+ deleteEntryUInt32HashList(new->data.enumval.enum_value.u32, parent->hashlist[0]);
+ break;
+
+ case AVP_TYPE_UNSIGNED64:
+ deleteEntryUInt64HashList(new->data.enumval.enum_value.u64, parent->hashlist[0]);
+ break;
+
+ case AVP_TYPE_FLOAT32:
+ deleteEntryFloat32HashList(new->data.enumval.enum_value.f32, parent->hashlist[0]);
+ break;
+
+ case AVP_TYPE_FLOAT64:
+ deleteEntryFloat64HashList(new->data.enumval.enum_value.f64, parent->hashlist[0]);
+ break;
+
+ default:
+ /* Invalid parent type basetype */
+ CHECK_PARAMS( parent = NULL );
+ }
+ goto error_unlock;
+ }
+#endif
/* A type_enum object is linked in it's parent 'type' object lists 1 and 2 by its name and values */
ret = fd_list_insert_ordered ( &parent->list[1], &new->list[0], (int (*)(void*, void *))order_enum_by_name, (void **)&locref );
if (ret)
@@ -1726,6 +1987,17 @@
break;
case DICT_AVP:
+#if USE_HASHLIST
+ ret = insertUInt32HashList(new->data.avp.avp_code, new, vendor->hashlist[0], (void **)&locref);
+ if (ret)
+ goto error_unlock;
+
+ ret = insertStringHashList(new->data.avp.avp_name, new, vendor->hashlist[1], (void **)&locref);
+ if (ret) {
+ deleteEntryUInt32HashList(new->data.avp.avp_code, vendor->hashlist[0]);
+ goto error_unlock;
+ }
+#endif
/* An avp object is linked in lists 1 and 2 of its vendor, by code and name */
ret = fd_list_insert_ordered ( &vendor->list[1], &new->list[0], (int (*)(void*, void *))order_avp_by_code, (void **)&locref );
if (ret)
@@ -1754,8 +2026,14 @@
case DICT_RULE:
/* A rule object is linked in list[2] of its parent command or AVP by the name of the AVP it refers */
ret = fd_list_insert_ordered ( &parent->list[2], &new->list[0], (int (*)(void*, void *))order_rule_by_avpvc, (void **)&locref );
- if (ret)
+ if (ret){
+ /*If the new rule is optional and the existing one is mandatory ==> override the existing rule to optional */
+ if(locref->data.rule.rule_position == RULE_REQUIRED && new->data.rule.rule_position == RULE_OPTIONAL){
+ TRACE_DEBUG(INFO, "Overriding rule to optional for AVP: %s", locref->data.rule.rule_avp->data.avp.avp_name);
+ locref->data.rule.rule_position = RULE_OPTIONAL;
+ }
goto error_unlock;
+ }
break;
default:
@@ -1766,6 +2044,9 @@
dict->dict_count[type]++;
/* Unlock the dictionary */
+#if ENABLE_LOCK_BYPASS
+ if (!dict->dict_bypass_lock)
+#endif
CHECK_POSIX_DO( ret = pthread_rwlock_unlock(&dict->dict_lock), goto error_free );
/* Save the pointer to the new object */
@@ -1779,6 +2060,9 @@
goto all_errors;
error_unlock:
+#if ENABLE_LOCK_BYPASS
+ if (!dict->dict_bypass_lock)
+#endif
CHECK_POSIX_DO( pthread_rwlock_unlock(&dict->dict_lock), /* continue */ );
if (ret == EEXIST) {
/* We have a duplicate key in locref. Check if the pointed object is the same or not */
@@ -1969,6 +2253,9 @@
dict = obj->dico;
/* Lock the dictionary for change */
+#if ENABLE_LOCK_BYPASS
+ if (!dict->dict_bypass_lock)
+#endif
CHECK_POSIX( pthread_rwlock_wrlock(&dict->dict_lock) );
/* check the object is not sentinel for another list */
@@ -1989,11 +2276,21 @@
destroy_object(obj);
/* Unlock */
+#if ENABLE_LOCK_BYPASS
+ if (!dict->dict_bypass_lock)
+#endif
CHECK_POSIX( pthread_rwlock_unlock(&dict->dict_lock) );
return ret;
}
+void fd_dict_bypass_lock( struct dictionary *dict, int bypass )
+{
+#if ENABLE_LOCK_BYPASS
+ if (dict && dict->dict_eyec == DICT_EYECATCHER)
+ dict->dict_bypass_lock = bypass;
+#endif
+}
int fd_dict_search ( struct dictionary * dict, enum dict_object_type type, int criteria, const void * what, struct dict_object **result, int retval )
{
@@ -2005,12 +2302,18 @@
CHECK_PARAMS( dict && (dict->dict_eyec == DICT_EYECATCHER) && CHECK_TYPE(type) );
/* Lock the dictionary for reading */
+#if ENABLE_LOCK_BYPASS
+ if (!dict->dict_bypass_lock)
+#endif
CHECK_POSIX( pthread_rwlock_rdlock(&dict->dict_lock) );
/* Now call the type-specific search function */
ret = dict_obj_info[type].search_fct (dict, criteria, what, result);
/* Unlock */
+#if ENABLE_LOCK_BYPASS
+ if (!dict->dict_bypass_lock)
+#endif
CHECK_POSIX( pthread_rwlock_unlock(&dict->dict_lock) );
/* Update the return value as needed */
@@ -2145,6 +2448,9 @@
new->dict_eyec = DICT_EYECATCHER;
/* Initialize the lock for the dictionary */
+#if ENABLE_LOCK_BYPASS
+ new->dict_bypass_lock = 0;
+#endif
CHECK_POSIX( pthread_rwlock_init(&new->dict_lock, NULL) );
/* Initialize the sentinel for vendors and AVP lists */
@@ -2154,6 +2460,13 @@
new->dict_vendors.datastr_len = CONSTSTRLEN(NO_VENDOR_NAME);
/* new->dict_vendors.list[0].o = NULL; *//* overwrite since element is also sentinel for this list. */
new->dict_vendors.dico = new;
+#if USE_HASHLIST
+ initUInt32HashList(&new->dict_vendors.hashlist[0]);
+ initStringHashList(&new->dict_vendors.hashlist[1]);
+ LOG_N("HASHLIST is enabled");
+#else
+ LOG_N("HASHLIST is disabled");
+#endif
/* Initialize the sentinel for applications */
init_object( &new->dict_applications, DICT_APPLICATION );
@@ -2194,6 +2507,9 @@
CHECK_PARAMS( dict && *dict && ((*dict)->dict_eyec == DICT_EYECATCHER) );
/* Acquire the write lock to make sure no other operation is ongoing */
+#if ENABLE_LOCK_BYPASS
+ if (!(*dict)->dict_bypass_lock)
+#endif
CHECK_POSIX( pthread_rwlock_wrlock(&(*dict)->dict_lock) );
/* Empty all the lists, free the elements */
@@ -2207,6 +2523,9 @@
}
/* Dictionary is empty, now destroy the lock */
+#if ENABLE_LOCK_BYPASS
+ if (!(*dict)->dict_bypass_lock)
+#endif
CHECK_POSIX( pthread_rwlock_unlock(&(*dict)->dict_lock) );
CHECK_POSIX( pthread_rwlock_destroy(&(*dict)->dict_lock) );
@@ -2243,6 +2562,9 @@
: parent->data.avp.avp_name);
/* Acquire the read lock */
+#if ENABLE_LOCK_BYPASS
+ if (!parent->dico->dict_bypass_lock)
+#endif
CHECK_POSIX( pthread_rwlock_rdlock(&parent->dico->dict_lock) );
/* go through the list and call the cb on each rule data */
@@ -2253,6 +2575,9 @@
}
/* Release the lock */
+#if ENABLE_LOCK_BYPASS
+ if (!parent->dico->dict_bypass_lock)
+#endif
CHECK_POSIX( pthread_rwlock_unlock(&parent->dico->dict_lock) );
return ret;
@@ -2268,6 +2593,9 @@
TRACE_ENTRY();
/* Acquire the read lock */
+#if ENABLE_LOCK_BYPASS
+ if (!dict->dict_bypass_lock)
+#endif
CHECK_POSIX_DO( pthread_rwlock_rdlock(&dict->dict_lock), return NULL );
/* Allocate an array to contain all the elements */
@@ -2281,6 +2609,9 @@
}
out:
/* Release the lock */
+#if ENABLE_LOCK_BYPASS
+ if (!dict->dict_bypass_lock)
+#endif
CHECK_POSIX_DO( pthread_rwlock_unlock(&dict->dict_lock), return NULL );
return ret;
diff --git a/libfdproto/hashlist.cpp b/libfdproto/hashlist.cpp
new file mode 100644
index 0000000..6fa6771
--- /dev/null
+++ b/libfdproto/hashlist.cpp
@@ -0,0 +1,404 @@
+
+#include <string>
+#include <unordered_map>
+
+extern "C" {
+ int initInt32HashList(void **hl);
+ void deleteInt32HashList(void *hl);
+ void deleteEntryInt32HashList(int32_t k, void *hl);
+ int insertInt32HashList(int32_t k, void *v, void *hl, void **duplicate);
+ int findInt32HashList(int32_t k, void *hl, void **result);
+
+ int initInt64HashList(void **hl);
+ void deleteInt64HashList(void *hl);
+ void deleteEntryInt64HashList(int64_t k, void *hl);
+ int insertInt64HashList(int64_t k, void *v, void *hl, void **duplicate);
+ int findInt64HashList(int64_t k, void *hl, void **result);
+
+ int initUInt32HashList(void **hl);
+ void deleteUInt32HashList(void *hl);
+ void deleteEntryUInt32HashList(uint32_t k, void *hl);
+ int insertUInt32HashList(uint32_t k, void *v, void *hl, void **duplicate);
+ int findUInt32HashList(uint32_t k, void *hl, void **result);
+
+ int initUInt64HashList(void **hl);
+ void deleteUInt64HashList(void *hl);
+ void deleteEntryUInt64HashList(uint64_t k, void *hl);
+ int insertUInt64HashList(uint64_t k, void *v, void *hl, void **duplicate);
+ int findUInt64HashList(uint64_t k, void *hl, void **result);
+
+ int initFloat32HashList(void **hl);
+ void deleteFloat32HashList(void *hl);
+ void deleteEntryFloat32HashList(float k, void *hl);
+ int insertFloat32HashList(float k, void *v, void *hl, void **duplicate);
+ int findFloat32HashList(float k, void *hl, void **result);
+
+ int initFloat64HashList(void **hl);
+ void deleteFloat64HashList(void *hl);
+ void deleteEntryFloat64HashList(double k, void *hl);
+ int insertFloat64HashList(double k, void *v, void *hl, void **duplicate);
+ int findFloat64HashList(double k, void *hl, void **result);
+
+ int initStringHashList(void **hl);
+ void deleteStringHashList(void *hl);
+ void deleteEntryStringHashList(const char *k, void *hl);
+ int insertStringHashList(const char *k, void *v, void *hl, void **duplicate);
+ int findStringHashList(const char *k, void *hl, void **result);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+int initInt32HashList(void **hl)
+{
+ *hl = (void*)(new std::unordered_map<int32_t,void*>());
+ return 0;
+}
+
+void deleteInt32HashList(void *hl)
+{
+ delete (std::unordered_map<int32_t,void*>*)hl;
+}
+
+void deleteEntryInt32HashList(int32_t k, void *hl)
+{
+ std::unordered_map<int32_t,void*> &l( *(std::unordered_map<int32_t,void*>*)hl );
+
+ l.erase(k);
+}
+
+int insertInt32HashList(int32_t k, void *v, void *hl, void **duplicate)
+{
+ std::unordered_map<int32_t,void*> &l( *(std::unordered_map<int32_t,void*>*)hl );
+
+ auto result = l.insert({k,v});
+
+ if (!result.second && duplicate)
+ *duplicate = result.first->second;
+
+ return result.second ? 0 : EEXIST;
+}
+
+int findInt32HashList(int32_t k, void *hl, void **result)
+{
+ if (hl == NULL || result == NULL)
+ return EINVAL;
+
+ int ret = 0;
+ std::unordered_map<int32_t,void*> &l( *(std::unordered_map<int32_t,void*>*)hl );
+
+ auto search = l.find(k);
+
+ if (search != l.end())
+ *result = search->second;
+ else
+ ret = ENOENT;
+
+ return ret;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+int initInt64HashList(void **hl)
+{
+ *hl = (void*)(new std::unordered_map<int64_t,void*>());
+ return 0;
+}
+
+void deleteInt64HashList(void *hl)
+{
+ delete (std::unordered_map<int64_t,void*>*)hl;
+}
+
+void deleteEntryInt64HashList(int64_t k, void *hl)
+{
+ std::unordered_map<int64_t,void*> &l( *(std::unordered_map<int64_t,void*>*)hl );
+
+ l.erase(k);
+}
+
+int insertInt64HashList(int64_t k, void *v, void *hl, void **duplicate)
+{
+ std::unordered_map<int64_t,void*> &l( *(std::unordered_map<int64_t,void*>*)hl );
+
+ auto result = l.insert({k,v});
+
+ if (!result.second && duplicate)
+ *duplicate = result.first->second;
+
+ return result.second ? 0 : EEXIST;
+}
+
+int findInt64HashList(int64_t k, void *hl, void **result)
+{
+ if (hl == NULL || result == NULL)
+ return EINVAL;
+
+ int ret = 0;
+ std::unordered_map<int64_t,void*> &l( *(std::unordered_map<int64_t,void*>*)hl );
+
+ auto search = l.find(k);
+
+ if (search != l.end())
+ *result = search->second;
+ else
+ ret = ENOENT;
+
+ return ret;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+int initUInt32HashList(void **hl)
+{
+ *hl = (void*)(new std::unordered_map<uint32_t,void*>());
+ return 0;
+}
+
+void deleteUInt32HashList(void *hl)
+{
+ delete (std::unordered_map<uint32_t,void*>*)hl;
+}
+
+void deleteEntryUInt32HashList(uint32_t k, void *hl)
+{
+ std::unordered_map<uint32_t,void*> &l( *(std::unordered_map<uint32_t,void*>*)hl );
+
+ l.erase(k);
+}
+
+int insertUInt32HashList(uint32_t k, void *v, void *hl, void **duplicate)
+{
+ std::unordered_map<uint32_t,void*> &l( *(std::unordered_map<uint32_t,void*>*)hl );
+
+ auto result = l.insert({k,v});
+
+ if (!result.second && duplicate)
+ *duplicate = result.first->second;
+
+ return result.second ? 0 : EEXIST;
+}
+
+int findUInt32HashList(uint32_t k, void *hl, void **result)
+{
+ if (hl == NULL || result == NULL)
+ return EINVAL;
+
+ int ret = 0;
+ std::unordered_map<uint32_t,void*> &l( *(std::unordered_map<uint32_t,void*>*)hl );
+
+ auto search = l.find(k);
+
+ if (search != l.end())
+ *result = search->second;
+ else
+ ret = ENOENT;
+
+ return ret;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+int initUInt64HashList(void **hl)
+{
+ *hl = (void*)(new std::unordered_map<uint64_t,void*>());
+ return 0;
+}
+
+void deleteUInt64HashList(void *hl)
+{
+ delete (std::unordered_map<uint64_t,void*>*)hl;
+}
+
+void deleteEntryUInt64HashList(uint64_t k, void *hl)
+{
+ std::unordered_map<uint64_t,void*> &l( *(std::unordered_map<uint64_t,void*>*)hl );
+
+ l.erase(k);
+}
+
+int insertUInt64HashList(uint64_t k, void *v, void *hl, void **duplicate)
+{
+ std::unordered_map<uint64_t,void*> &l( *(std::unordered_map<uint64_t,void*>*)hl );
+
+ auto result = l.insert({k,v});
+
+ if (!result.second && duplicate)
+ *duplicate = result.first->second;
+
+ return result.second ? 0 : EEXIST;
+}
+
+int findUInt64HashList(uint64_t k, void *hl, void **result)
+{
+ if (hl == NULL || result == NULL)
+ return EINVAL;
+
+ int ret = 0;
+ std::unordered_map<uint64_t,void*> &l( *(std::unordered_map<uint64_t,void*>*)hl );
+
+ auto search = l.find(k);
+
+ if (search != l.end())
+ *result = search->second;
+ else
+ ret = ENOENT;
+
+ return ret;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+int initFloat32HashList(void **hl)
+{
+ *hl = (void*)(new std::unordered_map<float,void*>());
+ return 0;
+}
+
+void deleteFloat32HashList(void *hl)
+{
+ delete (std::unordered_map<float,void*>*)hl;
+}
+
+void deleteEntryFloat32HashList(float k, void *hl)
+{
+ std::unordered_map<float,void*> &l( *(std::unordered_map<float,void*>*)hl );
+
+ l.erase(k);
+}
+
+int insertFloat32HashList(float k, void *v, void *hl, void **duplicate)
+{
+ std::unordered_map<float,void*> &l( *(std::unordered_map<float,void*>*)hl );
+
+ auto result = l.insert({k,v});
+
+ if (!result.second && duplicate)
+ *duplicate = result.first->second;
+
+ return result.second ? 0 : EEXIST;
+}
+
+int findFloat32HashList(float k, void *hl, void **result)
+{
+ if (hl == NULL || result == NULL)
+ return EINVAL;
+
+ int ret = 0;
+ std::unordered_map<float,void*> &l( *(std::unordered_map<float,void*>*)hl );
+
+ auto search = l.find(k);
+
+ if (search != l.end())
+ *result = search->second;
+ else
+ ret = ENOENT;
+
+ return ret;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+int initFloat64HashList(void **hl)
+{
+ *hl = (void*)(new std::unordered_map<double,void*>());
+ return 0;
+}
+
+void deleteFloat64HashList(void *hl)
+{
+ delete (std::unordered_map<double,void*>*)hl;
+}
+
+void deleteEntryFloat64HashList(double k, void *hl)
+{
+ std::unordered_map<double,void*> &l( *(std::unordered_map<double,void*>*)hl );
+
+ l.erase(k);
+}
+
+int insertFloat64HashList(double k, void *v, void *hl, void **duplicate)
+{
+ std::unordered_map<double,void*> &l( *(std::unordered_map<double,void*>*)hl );
+
+ auto result = l.insert({k,v});
+
+ if (!result.second && duplicate)
+ *duplicate = result.first->second;
+
+ return result.second ? 0 : EEXIST;
+}
+
+int findFloat64HashList(double k, void *hl, void **result)
+{
+ if (hl == NULL || result == NULL)
+ return EINVAL;
+
+ int ret = 0;
+ std::unordered_map<double,void*> &l( *(std::unordered_map<double,void*>*)hl );
+
+ auto search = l.find(k);
+
+ if (search != l.end())
+ *result = search->second;
+ else
+ ret = ENOENT;
+
+ return ret;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+int initStringHashList(void **hl)
+{
+ *hl = (void*)(new std::unordered_map<std::string,void*>());
+ return 0;
+}
+
+void deleteStringHashList(void *hl)
+{
+ delete (std::unordered_map<std::string,void*>*)hl;
+}
+
+void deleteEntryStringHashList(const char *k, void *hl)
+{
+ std::unordered_map<std::string,void*> &l( *(std::unordered_map<std::string,void*>*)hl );
+
+ l.erase(k);
+}
+
+int insertStringHashList(const char *k, void *v, void *hl, void **duplicate)
+{
+ std::unordered_map<std::string,void*> &l( *(std::unordered_map<std::string,void*>*)hl );
+
+ auto result = l.insert({k,v});
+
+ if (!result.second && duplicate)
+ *duplicate = result.first->second;
+
+ return result.second ? 0 : EEXIST;
+}
+
+int findStringHashList(const char *k, void *hl, void **result)
+{
+ if (hl == NULL || result == NULL)
+ return EINVAL;
+
+ int ret = 0;
+ std::unordered_map<std::string,void*> &l( *(std::unordered_map<std::string,void*>*)hl );
+
+ auto search = l.find(k);
+
+ if (search != l.end())
+ *result = search->second;
+ else
+ ret = ENOENT;
+
+ return ret;
+}
diff --git a/libfdproto/log.c b/libfdproto/log.c
index 7bbe307..0ea2130 100644
--- a/libfdproto/log.c
+++ b/libfdproto/log.c
@@ -129,6 +129,9 @@
void fd_log ( int loglevel, const char * format, ... )
{
va_list ap;
+
+ if (loglevel < fd_g_debug_lvl)
+ return;
(void)pthread_mutex_lock(&fd_log_lock);