Updated libcache

This commit is contained in:
William Guglielmo 2017-05-30 19:17:41 +02:00
parent 46284e1537
commit 4a751f9d05
4 changed files with 187 additions and 95 deletions

View file

@ -892,7 +892,7 @@ struct ndpi_detection_module_struct {
#endif
#endif
#ifdef NDPI_PROTOCOL_TINC
cache_t *tinc_cache;
cache_t tinc_cache;
#endif
ndpi_proto_defaults_t proto_defaults[NDPI_MAX_SUPPORTED_PROTOCOLS+NDPI_MAX_NUM_CUSTOM_PROTOCOLS];

View file

@ -1,65 +1,45 @@
#ifndef __LIBCACHE_H__
#define __LIBCACHE_H__
/**
* @file libcache.h
* @author William Guglielmo <william@deselmo.com>
* @brief File containing header of cache_t type.
*
*/
#ifndef __DESELMO_LIBCACHE_H__
#define __DESELMO_LIBCACHE_H__
#include <stdint.h>
/* Codes representing the result of some functions */
typedef enum {
CACHE_NO_ERROR = 0,
CACHE_CONTAINS_FALSE = 0,
CACHE_CONTAINS_TRUE,
CACHE_INVALID_INPUT,
CACHE_REMOVE_NOT_FOUND,
CACHE_MALLOC_ERROR
/**
* @brief Codes representing the result of some functions
*
*/
typedef enum cache_result {
CACHE_NO_ERROR = 0, /**< Returned by a function if no error occurs. */
CACHE_CONTAINS_FALSE = 0, /**< Returned by function cache_contains if item is not present. */
CACHE_CONTAINS_TRUE, /**< Returned by function cache_contains if item is present. */
CACHE_INVALID_INPUT, /**< Returned by a function if it is called with invalid input parameters. */
CACHE_REMOVE_NOT_FOUND, /**< Returned by function cache_remove if item is not present. */
CACHE_MALLOC_ERROR /**< Returned by a function if a malloc fail. */
} cache_result;
/* CACHE_T */
typedef struct cache_t cache_t;
/* CACHE_ENTRY */
typedef struct cache_entry cache_entry;
/* CACHE_ENTRY_MAP */
typedef struct cache_entry_map cache_entry_map;
/* STRUCT CACHE_T */
struct cache_t {
uint32_t size;
uint32_t max_size;
cache_entry *head;
cache_entry *tail;
cache_entry_map **map;
};
/* STRUCT CACHE_ENTRY */
struct cache_entry_map {
cache_entry *entry;
cache_entry_map *next;
};
/* STRUCT CACHE_ENTRY_MAP */
struct cache_entry {
void *item;
uint32_t item_size;
cache_entry *prev;
cache_entry *next;
};
typedef struct cache_t *cache_t;
/**
* Returns a new cache_t
* @brief Returns a new cache_t
*
* @par cache_max_size = max number of item that the new cache_t can contain
* @return a new cache_t, or NULL if an error occurred
*
*/
cache_t *cache_new(uint32_t cache_max_size);
cache_t cache_new(uint32_t cache_max_size);
/**
* Add an item in the specified cache_t
* @brief Add an item in the specified cache_t
*
* @par cache = the cache_t
* @par item = pointer to the item to add
@ -67,11 +47,11 @@ cache_t *cache_new(uint32_t cache_max_size);
* @return a code representing the result of the function
*
*/
cache_result cache_add(cache_t *cache, void *item, uint32_t item_size);
cache_result cache_add(cache_t cache, void *item, uint32_t item_size);
/**
* Check if an item is in the specified cache_t
* @brief Check if an item is in the specified cache_t
*
* @par cache = the cache_t
* @par item = pointer to the item to check
@ -79,11 +59,11 @@ cache_result cache_add(cache_t *cache, void *item, uint32_t item_size);
* @return a code representing the result of the function
*
*/
cache_result cache_contains(cache_t *cache, void *item, uint32_t item_size);
cache_result cache_contains(cache_t cache, void *item, uint32_t item_size);
/**
* Remove an item in the specified cache_t
* @brief Remove an item in the specified cache_t
*
* @par cache = the cache_t
* @par item = pointer to the item to remove
@ -91,15 +71,15 @@ cache_result cache_contains(cache_t *cache, void *item, uint32_t item_size);
* @return a code representing the result of the function
*
*/
cache_result cache_remove(cache_t *cache, void *item, uint32_t item_size);
cache_result cache_remove(cache_t cache, void *item, uint32_t item_size);
/**
* Free the specified cache_t
* @brief Free the specified cache_t
*
* @par alist = the cache
*
*/
void cache_free(cache_t *cache);
void cache_free(cache_t cache);
#endif

View file

@ -1,3 +1,11 @@
/**
* @file libcache.c
* @author William Guglielmo
* @brief File containing implementation of cache_t type.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
@ -7,6 +15,7 @@
// https://en.wikipedia.org/wiki/Jenkins_hash_function
#define HASH_FUNCTION jenkins_one_at_a_time_hash
uint32_t jenkins_one_at_a_time_hash(const uint8_t* key, size_t length) {
size_t i = 0;
uint32_t hash = 0;
@ -21,19 +30,62 @@ uint32_t jenkins_one_at_a_time_hash(const uint8_t* key, size_t length) {
return hash;
}
cache_entry_map *cache_entry_map_new() {
return (cache_entry_map *) calloc(sizeof(cache_entry_map), 1);
}
cache_entry *cache_entry_new() {
return (cache_entry *) calloc(sizeof(cache_entry), 1);
typedef struct cache_entry *cache_entry;
typedef struct cache_entry_map *cache_entry_map;
struct cache_t {
uint32_t size;
uint32_t max_size;
cache_entry head;
cache_entry tail;
cache_entry_map *map;
};
struct cache_entry_map {
cache_entry entry;
cache_entry_map next;
};
struct cache_entry {
void *item;
uint32_t item_size;
cache_entry prev;
cache_entry next;
};
void cache_touch_entry(cache_t cache, cache_entry entry) {
if(entry->prev) {
if(entry->next) {
entry->prev->next = entry->next;
entry->next->prev = entry->prev;
} else {
entry->prev->next = NULL;
cache->tail = entry->prev;
}
entry->prev = NULL;
entry->next = cache->head;
cache->head->prev = entry;
cache->head = entry;
}
}
cache_t *cache_new(uint32_t cache_max_size) {
cache_entry cache_entry_new() {
return (cache_entry) calloc(sizeof(struct cache_entry), 1);
}
cache_entry_map cache_entry_map_new() {
return (cache_entry_map) calloc(sizeof(struct cache_entry_map), 1);
}
cache_t cache_new(uint32_t cache_max_size) {
if(!cache_max_size) {
return NULL;
}
cache_t *cache = (cache_t *) calloc(sizeof(cache_t), 1);
cache_t cache = (cache_t) calloc(sizeof(struct cache_t), 1);
if(!cache) {
return NULL;
}
@ -41,7 +93,7 @@ cache_t *cache_new(uint32_t cache_max_size) {
cache->size = 0;
cache->max_size = cache_max_size;
cache->map = (cache_entry_map **) calloc(sizeof(cache_entry_map *), cache->max_size);
cache->map = (cache_entry_map *) calloc(sizeof(cache_entry_map ), cache->max_size);
if(!cache->map) {
free(cache);
@ -51,15 +103,15 @@ cache_t *cache_new(uint32_t cache_max_size) {
return cache;
}
cache_result cache_add(cache_t *cache, void *item, uint32_t item_size) {
cache_result cache_add(cache_t cache, void *item, uint32_t item_size) {
if(!cache || !item || !item_size) {
return CACHE_INVALID_INPUT;
}
uint32_t hash = jenkins_one_at_a_time_hash(item, item_size) % cache->max_size;
uint32_t hash = HASH_FUNCTION(item, item_size) % cache->max_size;
if((cache->map)[hash]) {
cache_entry_map *hash_entry_map = cache->map[hash];
cache_entry_map hash_entry_map = cache->map[hash];
while(hash_entry_map) {
if(item_size == hash_entry_map->entry->item_size &&
!memcmp(hash_entry_map->entry->item, item, item_size)) {
@ -70,32 +122,19 @@ cache_result cache_add(cache_t *cache, void *item, uint32_t item_size) {
}
if(hash_entry_map) {
cache_entry *entry = hash_entry_map->entry;
if(entry->prev) {
if(entry->next) {
entry->prev->next = entry->next;
entry->next->prev = entry->prev;
} else {
entry->prev->next = NULL;
cache->tail = entry->prev;
}
entry->prev = NULL;
entry->next = cache->head;
cache->head->prev = entry;
cache->head = entry;
}
cache_touch_entry(cache, hash_entry_map->entry);
return CACHE_NO_ERROR;
}
}
cache_entry *entry = cache_entry_new();
cache_entry entry = cache_entry_new();
if(!entry) {
return CACHE_MALLOC_ERROR;
}
cache_entry_map *map_entry = cache_entry_map_new();
cache_entry_map map_entry = cache_entry_map_new();
if(!map_entry) {
free(entry);
return CACHE_MALLOC_ERROR;
@ -121,12 +160,12 @@ cache_result cache_add(cache_t *cache, void *item, uint32_t item_size) {
cache->tail = entry;
}
} else {
cache_entry *tail = cache->tail;
cache_entry tail = cache->tail;
uint32_t hash = jenkins_one_at_a_time_hash(tail->item, tail->item_size) % cache->max_size;
uint32_t hash = HASH_FUNCTION(tail->item, tail->item_size) % cache->max_size;
if(cache->map[hash]) {
cache_entry_map *hash_entry_map_prev = NULL;
cache_entry_map *hash_entry_map = cache->map[hash];
cache_entry_map hash_entry_map_prev = NULL;
cache_entry_map hash_entry_map = cache->map[hash];
while(hash_entry_map) {
if(tail->item_size == hash_entry_map->entry->item_size &&
!memcmp(tail->item, hash_entry_map->entry->item, item_size)) {
@ -155,18 +194,20 @@ cache_result cache_add(cache_t *cache, void *item, uint32_t item_size) {
return CACHE_NO_ERROR;
}
cache_result cache_contains(cache_t *cache, void *item, uint32_t item_size) {
cache_result cache_contains(cache_t cache, void *item, uint32_t item_size) {
if(!cache || !item || !item_size) {
return CACHE_INVALID_INPUT;
}
uint32_t hash = jenkins_one_at_a_time_hash(item, item_size) % cache->max_size;
uint32_t hash = HASH_FUNCTION(item, item_size) % cache->max_size;
if(cache->map[hash]) {
cache_entry_map *hash_entry_map = cache->map[hash];
cache_entry_map hash_entry_map = cache->map[hash];
while(hash_entry_map) {
if(item_size == hash_entry_map->entry->item_size &&
!memcmp(hash_entry_map->entry->item, item, item_size)) {
cache_touch_entry(cache, hash_entry_map->entry);
return CACHE_CONTAINS_TRUE;
}
@ -177,16 +218,16 @@ cache_result cache_contains(cache_t *cache, void *item, uint32_t item_size) {
return CACHE_CONTAINS_FALSE;
}
cache_result cache_remove(cache_t *cache, void *item, uint32_t item_size) {
cache_result cache_remove(cache_t cache, void *item, uint32_t item_size) {
if(!cache || !item || !item_size) {
return CACHE_INVALID_INPUT;
}
uint32_t hash = jenkins_one_at_a_time_hash(item, item_size) % cache->max_size;
uint32_t hash = HASH_FUNCTION(item, item_size) % cache->max_size;
if(cache->map[hash]) {
cache_entry_map *hash_entry_map_prev = NULL;
cache_entry_map *hash_entry_map = cache->map[hash];
cache_entry_map hash_entry_map_prev = NULL;
cache_entry_map hash_entry_map = cache->map[hash];
while(hash_entry_map) {
if(item_size == hash_entry_map->entry->item_size &&
!memcmp(hash_entry_map->entry->item, item, item_size)) {
@ -205,7 +246,7 @@ cache_result cache_remove(cache_t *cache, void *item, uint32_t item_size) {
cache->map[hash] = hash_entry_map->next;
}
cache_entry *entry = hash_entry_map->entry;
cache_entry entry = hash_entry_map->entry;
if(entry->prev) {
entry->prev->next = entry->next;
@ -230,15 +271,15 @@ cache_result cache_remove(cache_t *cache, void *item, uint32_t item_size) {
return CACHE_REMOVE_NOT_FOUND;
}
void cache_free(cache_t *cache) {
void cache_free(cache_t cache) {
if(!cache) {
return;
}
int i;
for(i = 0; i < cache->max_size; i++) {
cache_entry_map *prev = NULL;
cache_entry_map *curr = cache->map[i];
cache_entry_map prev = NULL;
cache_entry_map curr = cache->map[i];
while(curr) {
prev = curr;
curr = curr->next;

71
src/lib/third_party/src/test.c vendored Normal file
View file

@ -0,0 +1,71 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "libcache.h"
int main() {
cache_t cache = cache_new(3);
long e;
e = 0;
assert(cache_add(cache, &e, sizeof(e)) == CACHE_NO_ERROR);
assert(cache_contains(cache, &e, sizeof(e)) == CACHE_CONTAINS_TRUE);
assert(cache_remove(cache, &e, sizeof(e)) == CACHE_NO_ERROR);
assert(cache_remove(cache, &e, sizeof(e)) == CACHE_REMOVE_NOT_FOUND);
assert(cache_contains(cache, &e, sizeof(e)) == CACHE_CONTAINS_FALSE);
assert(cache_add(cache, &e, sizeof(e)) == CACHE_NO_ERROR);
assert(cache_contains(cache, &e, sizeof(e)) == CACHE_CONTAINS_TRUE);
e = 1;
assert(cache_add(cache, &e, sizeof(e)) == CACHE_NO_ERROR);
assert(cache_contains(cache, &e, sizeof(e)) == CACHE_CONTAINS_TRUE);
e = 2;
assert(cache_add(cache, &e, sizeof(e)) == CACHE_NO_ERROR);
assert(cache_contains(cache, &e, sizeof(e)) == CACHE_CONTAINS_TRUE);
e = 3;
assert(cache_add(cache, &e, sizeof(e)) == CACHE_NO_ERROR);
assert(cache_contains(cache, &e, sizeof(e)) == CACHE_CONTAINS_TRUE);
e = 0;
assert(cache_contains(cache, &e, sizeof(e)) == CACHE_CONTAINS_FALSE);
e = 1;
assert(cache_contains(cache, &e, sizeof(e)) == CACHE_CONTAINS_TRUE);
e = 2;
assert(cache_contains(cache, &e, sizeof(e)) == CACHE_CONTAINS_TRUE);
e = 3;
assert(cache_contains(cache, &e, sizeof(e)) == CACHE_CONTAINS_TRUE);
e = 1;
assert(cache_add(cache, &e, sizeof(e)) == CACHE_NO_ERROR);
e = 4;
assert(cache_add(cache, &e, sizeof(e)) == CACHE_NO_ERROR);
e = 0;
assert(cache_contains(cache, &e, sizeof(e)) == CACHE_CONTAINS_FALSE);
e = 1;
assert(cache_contains(cache, &e, sizeof(e)) == CACHE_CONTAINS_TRUE);
e = 2;
assert(cache_contains(cache, &e, sizeof(e)) == CACHE_CONTAINS_FALSE);
e = 3;
assert(cache_contains(cache, &e, sizeof(e)) == CACHE_CONTAINS_TRUE);
e = 4;
assert(cache_contains(cache, &e, sizeof(e)) == CACHE_CONTAINS_TRUE);
// e = 5;
// assert(cache_add(cache, &e, sizeof(e)) == CACHE_NO_ERROR);
// e = 1;
// assert(cache_contains(cache, &e, sizeof(e)) == CACHE_CONTAINS_FALSE);
for(e = 0; e < 1000; e++) {
assert(cache_add(cache, &e, sizeof(e)) == CACHE_NO_ERROR);
assert(cache_contains(cache, &e, sizeof(e)) == CACHE_CONTAINS_TRUE);
}
for(e = 0; e < 997; e++) {
assert(cache_contains(cache, &e, sizeof(e)) == CACHE_CONTAINS_FALSE);
}
for(e = 997; e < 1000; e++) {
assert(cache_contains(cache, &e, sizeof(e)) == CACHE_CONTAINS_TRUE);
}
cache_free(cache);
puts("OK");
return 0;
}