#ifndef	ACL_CACHE_INCLUDE_H
#define	ACL_CACHE_INCLUDE_H

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

/**
 * д洢Ļ
 */
typedef struct ACL_CACHE_INFO {
	char *key;		/**< ֵ */
	void *value;		/**< û̬ */
	int   nrefer;		/**< ü */
	time_t when_timeout;	/**< ʱ */
	ACL_RING entry;		/**< ڲԱ */
} ACL_CACHE_INFO;

/**
 * 
 */
typedef struct ACL_CACHE { 
	ACL_HTABLE *table;	/**< ϣ */
	ACL_RING ring;		/**< ɾĶ */
	int   max_size;		/**< Сֵ */
	int   size;		/**< ǰеĻ */
	int   timeout;		/**< ÿʱ() */

	/**< ͷû̬ͷŻص */
	void  (*free_fn)(const ACL_CACHE_INFO*, void *);
	acl_pthread_mutex_t lock;	/**<  */
	ACL_SLICE *slice;		/**< ڴƬ */

	/* for acl_iterator */

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

/**
 * һأÿ󻺴ʱûصĿռ
 * @param max_size {int} ûص
 * @param timeout {int} ÿĻʱ
 * @param free_fn {void (*)(void*)} ûͷŻĺ
 * @return {ACL_CACHE*} ض
 */
ACL_API ACL_CACHE *acl_cache_create(int max_size, int timeout,
	void (*free_fn)(const ACL_CACHE_INFO*, void*));

/**
 * ͷһأԶ acl_cache_create()/3 еͷźͷŻ
 * @param cache {ACL_CACHE*} ض
 */
ACL_API void acl_cache_free(ACL_CACHE *cache);

/**
 * 򻺴ӱĶ
 * @param cache {ACL_CACHE*} ض
 * @param key {const char*} Ľֵ
 * @param value {void*} ̬
 * @return {ACL_CACHE_INFO*} Ľṹе value ûĶͬ,
 *    NULL ʾʧܣʧԭΪֵ̫ͬĶ
 *   ü0; ط NULL ʾӳɹͬһֵظӣ
 *   µ滻ɵݣҾݵͷźͷ
 */
ACL_API ACL_CACHE_INFO *acl_cache_enter(ACL_CACHE *cache, const char *key, void *value);

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

/**
 * ӻвĳĶĻϢ
 * @param cache {ACL_CACHE*} ض
 * @param key {const char*} ѯ
 * @return {ACL_CACHE_INFO*} ϢַΪNULLʱʾδҵ
 */
ACL_API ACL_CACHE_INFO *acl_cache_locate(ACL_CACHE *cache, const char *key);

/**
 * ӻɾĳ
 * @param cache {ACL_CACHE*} ض
 * @param info {ACL_CACHE_INFO*} ûĻϢ
 * @return {int} 0: ʾɾɹ; -1: ʾöü0ö󲻴
 */
ACL_API int acl_cache_delete(ACL_CACHE *cache, ACL_CACHE_INFO *info);

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

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

/**
 * ʹĳĻʱӳ
 * @param cache {ACL_CACHE*} ض
 * @param info {ACL_CACHE_INFO*} 
 * @param timeout {int} ʱ()
 */
ACL_API void acl_cache_update2(ACL_CACHE *cache, ACL_CACHE_INFO *info, int timeout);

/**
 * ʹĳĻʱӳ
 * @param cache {ACL_CACHE*} ض
 * @param key {const char*} ֵ
 * @param timeout {int} ʱ()
 */
ACL_API void acl_cache_update(ACL_CACHE *cache, const char *key, int timeout);

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

/**
 * ĳüֹǰɾ
 * @param cache {ACL_CACHE*} ض
 * @param key {const char*}
 */
ACL_API void acl_cache_refer2(ACL_CACHE *cache, const char *key);

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

/**
 * ĳü
 * @param cache {ACL_CACHE*} ض
 * @param key {const char*}
 */
ACL_API void acl_cache_unrefer2(ACL_CACHE *cache, const char *key);

/**
 * ضڶ߳ʱ
 * @param cache {ACL_CACHE*} ض
 */
ACL_API void acl_cache_lock(ACL_CACHE *cache);

/**
 * ضڶ߳ʱ
 * @param cache {ACL_CACHE*} ض
 */
ACL_API void acl_cache_unlock(ACL_CACHE *cache);

/**
 * еж
 * @param cache {ACL_CACHE*} ض
 * @param walk_fn {void (*)(ACL_CACHE_INFO*, void*)} ص
 * @param arg {void *} walk_fn()/2 еĵڶ
 */
ACL_API void acl_cache_walk(ACL_CACHE *cache, void (*walk_fn)(ACL_CACHE_INFO *, void *), void *arg);

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

/**
 * ǰлĸ
 * @param cache {ACL_CACHE*} ض
 * @return {int} Ķ
 */
ACL_API int acl_cache_size(ACL_CACHE *cache);

#ifdef	__cplusplus
}
#endif

#endif
