#ifndef _NFS4_DB_IMPL_H
#define _NFS4_DB_IMPL_H
#ifdef __cplusplus
extern "C" {
#endif
#define SEARCH_DEBUG 0x0001
#define CREATE_DEBUG 0x0002
#define CACHED_DEBUG 0x0004
#define DESTROY_DEBUG 0x0008
#define REAP_DEBUG 0x0010
#define OTHER_DEBUG 0x0020
#define WALK_DEBUG 0x0040
typedef struct rfs4_link {
struct rfs4_link *next;
struct rfs4_link *prev;
rfs4_dbe_t *entry;
} rfs4_link_t;
struct rfs4_dbe {
kmutex_t dbe_lock[1];
uint32_t dbe_refcnt;
unsigned dbe_skipsearch:1;
unsigned dbe_invalid:1;
unsigned dbe_reserved:31;
time_t dbe_time_rele;
id_t dbe_id;
kcondvar_t dbe_cv[1];
rfs4_entry_t dbe_data;
rfs4_table_t *dbe_table;
rfs4_link_t dbe_indices[1];
};
typedef struct rfs4_bucket {
krwlock_t dbk_lock[1];
rfs4_link_t *dbk_head;
} rfs4_bucket_t;
struct rfs4_index {
uint32_t dbi_tblidx;
bool_t dbi_createable;
rfs4_table_t *dbi_table;
char *dbi_keyname;
rfs4_bucket_t *dbi_buckets;
uint32_t (*dbi_hash)(void *);
bool_t (*dbi_compare)(rfs4_entry_t, void *);
void *(*dbi_mkkey)(rfs4_entry_t);
struct rfs4_index *dbi_inext;
};
struct rfs4_table {
rfs4_table_t *dbt_tnext;
struct rfs4_database *dbt_db;
krwlock_t dbt_t_lock[1];
kmutex_t dbt_lock[1];
char *dbt_name;
id_space_t *dbt_id_space;
time_t dbt_min_cache_time;
time_t dbt_max_cache_time;
uint32_t dbt_usize;
uint32_t dbt_maxentries;
uint32_t dbt_len;
uint32_t dbt_count;
uint32_t dbt_idxcnt;
uint32_t dbt_maxcnt;
uint32_t dbt_ccnt;
uint32_t dbt_id_lwat;
uint32_t dbt_id_hwat;
time_t dbt_id_reap;
rfs4_index_t *dbt_indices;
bool_t (*dbt_create)(rfs4_entry_t, void *data);
void (*dbt_destroy)(rfs4_entry_t);
bool_t (*dbt_expiry)(rfs4_entry_t);
kmem_cache_t *dbt_mem_cache;
uint32_t dbt_debug;
unsigned dbt_reaper_shutdown:1;
kcondvar_t dbt_reaper_wait;
kmutex_t dbt_reaper_cv_lock;
callb_cpr_t dbt_reaper_cpr_info;
};
struct rfs4_database {
kmutex_t db_lock[1];
uint32_t db_debug_flags;
uint32_t db_shutdown_count;
kcondvar_t db_shutdown_wait;
rfs4_table_t *db_tables;
};
#define RFS4_RECLAIM_PERCENT 10
#define RFS4_REAP_INTERVAL 300
#define HASH(idx, key) (idx->dbi_hash(key) % idx->dbi_table->dbt_len)
#define ENQUEUE(head, l) { \
(l)->prev = NULL; \
(l)->next = (head); \
if ((l)->next) \
(l)->next->prev = (l); \
(head) = (l); \
}
#define DEQUEUE(head, l) { \
if ((l)->prev) \
(l)->prev->next = (l)->next; \
else \
(head) = (l)->next; \
if ((l)->next) \
(l)->next->prev = (l)->prev; \
}
#define INVALIDATE_ADDR(a) ((a) = (void *)((unsigned long)(a) | 1L))
#define VALIDATE_ADDR(a) ((a) = (void *)((unsigned long)(a) & ~1L))
#define INVALID_ADDR(a) (((unsigned long)(a) & 1L))
#define INVALID_LINK(l) (INVALID_ADDR(l->entry))
#define ENQUEUE_IDX(bp, l) { \
rw_enter((bp)->dbk_lock, RW_WRITER); \
ENQUEUE((bp)->dbk_head, l); \
VALIDATE_ADDR((l)->entry); \
rw_exit((bp)->dbk_lock); \
}
#define DEQUEUE_IDX(bp, l) { \
rw_enter((bp)->dbk_lock, RW_WRITER); \
INVALIDATE_ADDR((l)->entry); \
DEQUEUE((bp)->dbk_head, l); \
rw_exit((bp)->dbk_lock); \
}
#ifdef __cplusplus
}
#endif
#endif