| /* |
| * CDDL HEADER START |
| * |
| * The contents of this file are subject to the terms of the |
| * Common Development and Distribution License (the "License"). |
| * You may not use this file except in compliance with the License. |
| * |
| * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
| * or http://www.opensolaris.org/os/licensing. |
| * See the License for the specific language governing permissions |
| * and limitations under the License. |
| * |
| * When distributing Covered Code, include this CDDL HEADER in each |
| * file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
| * If applicable, add the following below this CDDL HEADER, with the |
| * fields enclosed by brackets "[]" replaced with your own identifying |
| * information: Portions Copyright [yyyy] [name of copyright owner] |
| * |
| * CDDL HEADER END |
| */ |
| /* |
| * Copyright 2009 Sun Microsystems, Inc. All rights reserved. |
| * Use is subject to license terms. |
| */ |
| |
| #ifndef _NFS4_DB_IMPL_H |
| #define _NFS4_DB_IMPL_H |
| |
| /* |
| * This is a private header file. Applications should not directly include |
| * this file. |
| */ |
| |
| #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 |
| |
| /* |
| * A database is made up of a collection of tables. |
| * Tables are in turn made up of a collection of |
| * entries. Each table may haveone or more indices |
| * associtated with it. |
| */ |
| |
| /* Private implementation */ |
| 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]; /* Exclusive lock for entry */ |
| uint32_t dbe_refcnt; /* # of references */ |
| unsigned dbe_skipsearch:1; /* skip search */ |
| unsigned dbe_invalid:1; /* invalid/"freed" entry */ |
| unsigned dbe_reserved:31; |
| time_t dbe_time_rele; /* Time of last rele */ |
| id_t dbe_id; /* unique identifier */ |
| kcondvar_t dbe_cv[1]; |
| rfs4_entry_t dbe_data; |
| rfs4_table_t *dbe_table; |
| rfs4_link_t dbe_indices[1]; /* Array of indices for entry */ |
| }; |
| |
| typedef struct rfs4_bucket { |
| krwlock_t dbk_lock[1]; /* lock hash chain */ |
| rfs4_link_t *dbk_head; |
| } rfs4_bucket_t; |
| |
| struct rfs4_index { |
| uint32_t dbi_tblidx; /* which indice in entry */ |
| bool_t dbi_createable; /* Can create entries */ |
| rfs4_table_t *dbi_table; /* Pointer to table */ |
| char *dbi_keyname; /* String rep of key */ |
| rfs4_bucket_t *dbi_buckets; /* Hash buckets */ |
| uint32_t (*dbi_hash)(void *); /* Given key find bucket */ |
| bool_t (*dbi_compare)(rfs4_entry_t, void *); /* Key match entry? */ |
| void *(*dbi_mkkey)(rfs4_entry_t); /* Given data generate a key */ |
| struct rfs4_index *dbi_inext; /* next index on table */ |
| }; |
| |
| struct rfs4_table { |
| rfs4_table_t *dbt_tnext; /* next table in db */ |
| struct rfs4_database *dbt_db; /* db that holds this table */ |
| krwlock_t dbt_t_lock[1]; /* lock table for resize */ |
| kmutex_t dbt_lock[1]; /* mutex for count and cached */ |
| char *dbt_name; /* Table name */ |
| id_space_t *dbt_id_space; /* space for unique entry ids */ |
| time_t dbt_min_cache_time; /* How long to cache entries */ |
| time_t dbt_max_cache_time; /* How long to cache entries */ |
| uint32_t dbt_usize; /* User entry size */ |
| uint32_t dbt_maxentries; /* max # of entries in table */ |
| uint32_t dbt_len; /* # of buckets in table */ |
| uint32_t dbt_count; /* # of entries in table */ |
| uint32_t dbt_idxcnt; /* # of indices in table */ |
| uint32_t dbt_maxcnt; /* max # of indices */ |
| uint32_t dbt_ccnt; /* # of creatable entries */ |
| uint32_t dbt_id_lwat; /* lo wtrmrk; 50% ids in use */ |
| uint32_t dbt_id_hwat; /* hi wtrmrk; 75% ids in use */ |
| time_t dbt_id_reap; /* table's reap interval */ |
| rfs4_index_t *dbt_indices; /* list of indices */ |
| /* Given entry and data construct entry */ |
| bool_t (*dbt_create)(rfs4_entry_t, void *data); |
| void (*dbt_destroy)(rfs4_entry_t); /* Destroy entry */ |
| bool_t (*dbt_expiry)(rfs4_entry_t); /* Has this entry expired */ |
| kmem_cache_t *dbt_mem_cache; /* Cache for table entries */ |
| uint32_t dbt_debug; /* Debug Flags */ |
| /* set of vars used for managing the reaper thread */ |
| unsigned dbt_reaper_shutdown:1; /* table shutting down? */ |
| kcondvar_t dbt_reaper_wait; /* reaper thread waits here */ |
| kmutex_t dbt_reaper_cv_lock; /* lock used for cpr wait */ |
| callb_cpr_t dbt_reaper_cpr_info; /* cpr the reaper thread */ |
| }; |
| |
| struct rfs4_database { |
| kmutex_t db_lock[1]; |
| uint32_t db_debug_flags; /* Table debug flags to set */ |
| uint32_t db_shutdown_count; /* count to manage shutdown */ |
| kcondvar_t db_shutdown_wait; /* where the shutdown waits */ |
| rfs4_table_t *db_tables; /* list of tables in db */ |
| }; |
| |
| #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 /* _NFS4_DB_IMPL_H */ |