/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _NFS4_DB_IMPL_H #define _NFS4_DB_IMPL_H #pragma ident "%Z%%M% %I% %E% SMI" /* * 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; struct rfs4_dbe { kmutex_t lock[1]; /* Exclusive lock for entry */ uint32_t refcnt; /* # of references */ unsigned skipsearch:1; /* skip search */ unsigned invalid:1; /* invalid/"freed" entry */ unsigned reserved:31; time_t time_rele; /* Time of last rele */ id_t id; /* unique identifier */ kcondvar_t cv[1]; rfs4_entry_t data; rfs4_table_t *table; rfs4_link indices[1]; /* Array of indices for entry */ }; typedef struct rfs4_bucket { krwlock_t lock[1]; /* lock hash chain */ rfs4_link *head; } rfs4_bucket; struct rfs4_index { uint32_t tblidx; /* which indice in entry */ bool_t createable; /* Can create entries */ rfs4_table_t *table; /* Pointer to table */ char *keyname; /* String rep of key */ rfs4_bucket *buckets; /* Hash buckets */ uint32_t (*hash)(void *key); /* Given key find bucket */ bool_t (*compare)(rfs4_entry_t, void *key); /* Key match entry? */ void *(*mkkey)(rfs4_entry_t); /* Given data generate a key */ struct rfs4_index *inext; /* next index on table */ }; struct rfs4_table { rfs4_table_t *tnext; /* next table in db */ struct rfs4_database *dbp; /* db that holds this table */ krwlock_t t_lock[1]; /* lock table for resize */ kmutex_t lock[1]; /* mutex for count and cached */ char *name; /* Table name */ id_space_t *id_space; /* space for unique entry ids */ time_t min_cache_time; /* How long to cache entries */ time_t max_cache_time; /* How long to cache entries */ uint32_t usize; /* User entry size */ uint32_t maxentries; /* max # of entries in table */ uint32_t len; /* # of buckets in table */ uint32_t count; /* # of entries in table */ uint32_t idxcnt; /* # of indices in table */ uint32_t maxcnt; /* max # of indices */ uint32_t ccnt; /* # of creatable entries */ rfs4_index_t *indices; /* list of indices */ /* Given entry and data construct entry */ bool_t (*create)(rfs4_entry_t, void *data); void (*destroy)(rfs4_entry_t); /* Destroy entry */ bool_t (*expiry)(rfs4_entry_t); /* Has this entry expired */ kmem_cache_t *mem_cache; /* Cache for table entries */ uint32_t debug; /* Debug Flags */ /* set of vars used for managing the reaper thread */ unsigned reaper_shutdown:1; /* table shutting down? */ kcondvar_t reaper_wait; /* reaper thread waits here */ kmutex_t reaper_cv_lock; /* lock used for cpr wait */ callb_cpr_t reaper_cpr_info; /* cpr the reaper thread */ }; struct rfs4_database { kmutex_t lock[1]; uint32_t debug_flags; /* Table debug flags to set */ uint32_t shutdown_count; /* count to manage shutdown */ kcondvar_t shutdown_wait; /* where the shutdown waits */ rfs4_table_t *tables; /* list of tables in db */ }; #define RFS4_RECLAIM_PERCENT 10 #define RFS4_REAP_INTERVAL 300 #define HASH(idx, key) (idx->hash(key) % idx->table->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)->lock, RW_WRITER); \ ENQUEUE((bp)->head, l); \ VALIDATE_ADDR((l)->entry); \ rw_exit((bp)->lock); \ } #define DEQUEUE_IDX(bp, l) { \ rw_enter((bp)->lock, RW_WRITER); \ INVALIDATE_ADDR((l)->entry); \ DEQUEUE((bp)->head, l); \ rw_exit((bp)->lock); \ } #ifdef __cplusplus } #endif #endif /* _NFS4_DB_IMPL_H */