#ifndef	ACL_CACHE2_INCLUDE_H
#define	ACL_CACHE2_INCLUDE_H

#ifdef	__cplusplus
extern "C" {
#endif
#include "acl_define.h"
#include <time.h>

typedef struct ACL_CACHE2 ACL_CACHE2;

/**
 * д洢Ļ
 */
typedef struct ACL_CACHE2_INFO {
	char  *key;		/**< ֵ */
	void  *value;		/**< û̬ */
	int    nrefer;		/**< ü */
	time_t when_timeout;	/**< ʱ */
	ACL_CACHE2* cache;	/**< û */
} ACL_CACHE2_INFO;

/**
 * 
 */
struct ACL_CACHE2 { 
	int   max_size;		/**< Сֵ */
	int   size;		/**< ǰеĻ */
	void *ctx;		/**< ⲿö */

	/**< ͷû̬ͷŻص */
	void  (*free_fn)(const ACL_CACHE2_INFO*, void *);

	/* for acl_iterator */

	/* ȡͷ */
	void *(*iter_head)(ACL_ITER*, struct ACL_CACHE2*);
	/* ȡһ */
	void *(*iter_next)(ACL_ITER*, struct ACL_CACHE2*);
	/* ȡβ */
	void *(*iter_tail)(ACL_ITER*, struct ACL_CACHE2*);
	/* ȡһ */
	void *(*iter_prev)(ACL_ITER*, struct ACL_CACHE2*);
	/* ȡĵǰԱṹ */
	ACL_CACHE2_INFO *(*iter_info)(ACL_ITER*, struct ACL_CACHE2*);
};

/**
 * static void free_callback(const ACL_CACHE2_INFO *info, void *value) {
 * 	printf("Free key=%s\r\n", info->key);
 * 	free(value);
 * }
 *
 * void test() {
 * 	ACL_CACHE2 *cache = acl_cache2_create(100, free_callback);
 * 	const char *key = "test-key";
 * 	char *buf = strdup("test-value"), *value;
 * 	acl_cache2_enter(cache, key, value, 100);
 * 	value = (char*) acl_cache2_find(cache, key);
 * 	printf("The key=%s, value=%s\r\n", key, value ? value : "Not found");
 * 	ACL_ITER iter;
 * 	acl_foreach(iter, cache) {
 * 		value = (char*) iter.data;
 * 		key = iter.key;
 * 		...
 * 	}
 * }
 */

/**
 * һأÿ󻺴ʱûصĿռ
 * @param max_size {int} ûصƣֵ <= 0ڲƻ
 * @param free_fn {void (*)(void*)} ûͷŻĺ
 * @return {ACL_CACHE2*} ض
 */
ACL_API ACL_CACHE2 *acl_cache2_create(int max_size,
	void (*free_fn)(const ACL_CACHE2_INFO*, void*));

/**
 * ͷһ
 * @param cache2 {ACL_CACHE2*} ض
 */
ACL_API void acl_cache2_free(ACL_CACHE2 *cache2);

/**
 * 򻺴ӱĶ
 * @param cache2 {ACL_CACHE2*} ض
 * @param key {const char*} Ľֵ
 * @param value {void*} ̬
 * @param timeout {int} ÿĻʱ
 * @return {ACL_CACHE2_INFO*} Ľṹе value û
 *  ͬ,  NULL ʾʧܣʧԭΪ̫ͬ
 *  ֵĶü0; ط NULL ʾӳɹͬһ
 *  ֵظӣµ滻ɵݣҾݵͷźͷ
 */
ACL_API ACL_CACHE2_INFO *acl_cache2_enter(ACL_CACHE2 *cache2,
	const char *key, void *value, int timeout);

/**
 * ӻвĳĶ
 * @param cache2 {ACL_CACHE2*} ض
 * @param key {const char*} ѯ
 * @return {void*} ûĵַΪNULLʱʾδҵ
 */
ACL_API void *acl_cache2_find(ACL_CACHE2 *cache2, const char *key);

/**
 * ӻвĳĶĻϢ
 * @param cache2 {ACL_CACHE2*} ض
 * @param key {const char*} ѯ
 * @return {ACL_CACHE2_INFO*} ϢַΪNULLʱʾδҵ
 */
ACL_API ACL_CACHE2_INFO *acl_cache2_locate(ACL_CACHE2 *cache2, const char *key);

/**
 * ӻɾĳ
 * @param cache2 {ACL_CACHE2*} ض
 * @param info {ACL_CACHE2_INFO*} ûĻϢ
 * @return {int} 0: ʾɾɹ; -1: ʾöü0ö󲻴
 */
ACL_API int acl_cache2_delete(ACL_CACHE2 *cache2, ACL_CACHE2_INFO *info);

/**
 * ӻɾĳ
 * @param cache2 {ACL_CACHE2*} ض
 * @param key {const char*} ֵ
 * @return {int} 0: ʾɾɹ; -1: ʾöü0ö󲻴
 */
ACL_API int acl_cache2_delete2(ACL_CACHE2 *cache2, const char *key);

/**
 * ʹеĹڶԶɾ
 * @param cache2 {ACL_CACHE2*} ض
 * @return {int} >= 0: ԶɾĻĸ
 */
ACL_API int acl_cache2_timeout(ACL_CACHE2 *cache2);

/**
 * ʹĳĻʱӳ
 * @param cache2 {ACL_CACHE2*} ض
 * @param info {ACL_CACHE2_INFO*} 
 * @param timeout {int} ʱ()
 * @return {ACL_CACHE2_INFO*} ط NULL ʾΪ NULL ʾ key 
 */
ACL_API ACL_CACHE2_INFO *acl_cache2_update2(ACL_CACHE2 *cache2,
	ACL_CACHE2_INFO *info, int timeout);

/**
 * ʹĳĻʱӳ
 * @param cache2 {ACL_CACHE2*} ض
 * @param key {const char*} ֵ
 * @param timeout {int} ʱ()
 * @return {ACL_CACHE2_INFO*} ط NULL ʾΪ NULL ʾ key 
 */
ACL_API ACL_CACHE2_INFO *acl_cache2_update(ACL_CACHE2 *cache2,
	const char *key, int timeout);

/**
 * ӻ»еĶ
 * @param key {const char*} Ľֵ
 * @param value {void*} ̬
 * @param timeout {int} ÿĻʱ
 * @param exist {int*}  NULL ʱ key  1 0
 * @return {ACL_CACHE2_INFO*} Ľṹе value û
 *  ͬ key ¶¾ɶ󣻷 NULL
 *  ʾʧܣǸ·ʽӦעͷʱĶ̬
 */
ACL_API ACL_CACHE2_INFO *acl_cache2_upsert(ACL_CACHE2 *cache2,
	const char *key, void *value, int timeout, int *exist);
	
/**
 * ȡʱͷ󣬵߿ɴ ACL_CACHE2_INFO::value Ӧö
 * @param cache2 {ACL_CACHE2*}
 * @return {ACL_CACHE2_INFO*}  NULL ʾΪ
 */
ACL_API ACL_CACHE2_INFO *acl_cache2_head(ACL_CACHE2 *cache2);

/**
 * ȡʱβ󣬵߿ɴ ACL_CACHE2_INFO::value Ӧö
 * @param cache2 {ACL_CACHE2*}
 * @return {ACL_CACHE2_INFO*}  NULL ʾΪ
 */
ACL_API ACL_CACHE2_INFO *acl_cache2_tail(ACL_CACHE2 *cache2);

/**
 * ĳüֹǰɾ
 * @param info {ACL_CACHE2_INFO*} ûĻϢ
 */
ACL_API void acl_cache2_refer(ACL_CACHE2_INFO *info);

/**
 * ĳüֹǰɾ
 * @param cache2 {ACL_CACHE2*} ض
 * @param key {const char*}
 */
ACL_API void acl_cache2_refer2(ACL_CACHE2 *cache2, const char *key);

/**
 * ĳü
 * @param info {ACL_CACHE2_INFO*} ûĻϢ
 */
ACL_API void acl_cache2_unrefer(ACL_CACHE2_INFO *info);

/**
 * ĳü
 * @param cache2 {ACL_CACHE2*} ض
 * @param key {const char*}
 */
ACL_API void acl_cache2_unrefer2(ACL_CACHE2 *cache2, const char *key);

/**
 * ضڶ߳ʱ
 * @param cache2 {ACL_CACHE2*} ض
 */
ACL_API void acl_cache2_lock(ACL_CACHE2 *cache2);

/**
 * ضڶ߳ʱ
 * @param cache2 {ACL_CACHE2*} ض
 */
ACL_API void acl_cache2_unlock(ACL_CACHE2 *cache2);

/**
 * еж
 * @param cache2 {ACL_CACHE2*} ض
 * @param walk_fn {void (*)(ACL_CACHE2_INFO*, void*)} ص
 * @param arg {void *} walk_fn()/2 еĵڶ
 */
ACL_API void acl_cache2_walk(ACL_CACHE2 *cache2,
	void (*walk_fn)(ACL_CACHE2_INFO *, void *), void *arg);

/**
 * ջеĻĳȻڱҷǿɾ򽫲ᱻ
 * @param cache2 {ACL_CACHE2*} ض
 * @param force {int} 0ʹĳü0Ҳᱻɾ
 * @return {int} Ļ
 */
ACL_API int acl_cache2_clean(ACL_CACHE2 *cache2, int force);

/**
 * ǰлĸ
 * @param cache2 {ACL_CACHE2*} ض
 * @return {int} Ķ
 */
ACL_API int acl_cache2_size(ACL_CACHE2 *cache2);

#ifdef	__cplusplus
}
#endif

#endif
