1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#ifndef	_NFS4_DB_IMPL_H
27#define	_NFS4_DB_IMPL_H
28
29/*
30 * This is a private header file.  Applications should not directly include
31 * this file.
32 */
33
34#ifdef	__cplusplus
35extern "C" {
36#endif
37
38#define	SEARCH_DEBUG	0x0001
39#define	CREATE_DEBUG	0x0002
40#define	CACHED_DEBUG	0x0004
41#define	DESTROY_DEBUG	0x0008
42#define	REAP_DEBUG	0x0010
43#define	OTHER_DEBUG	0x0020
44#define	WALK_DEBUG	0x0040
45
46/*
47 * A database is made up of a collection of tables.
48 * Tables are in turn made up of a collection of
49 * entries. Each table may haveone or more indices
50 * associtated with it.
51 */
52
53/* Private implementation */
54typedef struct rfs4_link {
55	struct rfs4_link *next;
56	struct rfs4_link *prev;
57	rfs4_dbe_t *entry;
58} rfs4_link_t;
59
60struct rfs4_dbe {
61	kmutex_t	dbe_lock[1];		/* Exclusive lock for entry */
62	uint32_t	dbe_refcnt;		/* # of references */
63	unsigned	dbe_skipsearch:1;	/* skip search */
64	unsigned	dbe_invalid:1;		/* invalid/"freed" entry */
65	unsigned	dbe_reserved:31;
66	time_t		dbe_time_rele;		/* Time of last rele */
67	id_t		dbe_id;			/* unique identifier */
68	kcondvar_t	dbe_cv[1];
69	rfs4_entry_t	dbe_data;
70	rfs4_table_t	*dbe_table;
71	rfs4_link_t	dbe_indices[1];		/* Array of indices for entry */
72};
73
74typedef struct rfs4_bucket {
75	krwlock_t	dbk_lock[1];		/* lock hash chain */
76	rfs4_link_t	*dbk_head;
77} rfs4_bucket_t;
78
79struct rfs4_index {
80	uint32_t	dbi_tblidx;		/* which indice in entry */
81	bool_t		dbi_createable;		/* Can create entries */
82	rfs4_table_t	*dbi_table;		/* Pointer to table */
83	char		*dbi_keyname;		/* String rep of key */
84	rfs4_bucket_t	*dbi_buckets;		/* Hash buckets */
85	uint32_t (*dbi_hash)(void *);		/* Given key find bucket */
86	bool_t (*dbi_compare)(rfs4_entry_t, void *);	/* Key match entry? */
87	void *(*dbi_mkkey)(rfs4_entry_t);	/* Given data generate a key */
88	struct rfs4_index *dbi_inext;		/* next index on table */
89};
90
91struct rfs4_table {
92	rfs4_table_t	*dbt_tnext;		/* next table in db */
93	struct rfs4_database *dbt_db;		/* db that holds this table */
94	krwlock_t	dbt_t_lock[1];		/* lock table for resize */
95	kmutex_t	dbt_lock[1];		/* mutex for count and cached */
96	char		*dbt_name;		/* Table name */
97	id_space_t	*dbt_id_space;		/* space for unique entry ids */
98	time_t	dbt_min_cache_time;		/* How long to cache entries */
99	time_t	dbt_max_cache_time;		/* How long to cache entries */
100	uint32_t	dbt_usize;		/* User entry size */
101	uint32_t	dbt_maxentries;		/* max # of entries in table */
102	uint32_t	dbt_len;		/* # of buckets in table */
103	uint32_t	dbt_count;		/* # of entries in table */
104	uint32_t	dbt_idxcnt;		/* # of indices in table */
105	uint32_t	dbt_maxcnt;		/* max # of indices */
106	uint32_t	dbt_ccnt;		/* # of creatable entries */
107	uint32_t	dbt_id_lwat;		/* lo wtrmrk; 50% ids in use */
108	uint32_t	dbt_id_hwat;		/* hi wtrmrk; 75% ids in use */
109	time_t		dbt_id_reap;		/* table's reap interval */
110	rfs4_index_t	*dbt_indices;		/* list of indices */
111	/* Given entry and data construct entry */
112	bool_t (*dbt_create)(rfs4_entry_t, void *data);
113	void (*dbt_destroy)(rfs4_entry_t);	/* Destroy entry */
114	bool_t (*dbt_expiry)(rfs4_entry_t);	/* Has this entry expired */
115	kmem_cache_t	*dbt_mem_cache;		/* Cache for table entries */
116	uint32_t	dbt_debug;		/* Debug Flags */
117	/* set of vars used for managing the reaper thread */
118	unsigned	dbt_reaper_shutdown:1;	/* table shutting down? */
119	kcondvar_t	dbt_reaper_wait;	/* reaper thread waits here */
120	kmutex_t	dbt_reaper_cv_lock;	/* lock used for cpr wait */
121	callb_cpr_t	dbt_reaper_cpr_info;	/* cpr the reaper thread */
122};
123
124struct rfs4_database {
125	kmutex_t	db_lock[1];
126	uint32_t	db_debug_flags;		/* Table debug flags to set */
127	uint32_t	db_shutdown_count;	/* count to manage shutdown */
128	kcondvar_t	db_shutdown_wait;	/* where the shutdown waits */
129	rfs4_table_t	*db_tables;		/* list of tables in db */
130};
131
132#define	RFS4_RECLAIM_PERCENT 10
133#define	RFS4_REAP_INTERVAL 300
134
135#define	HASH(idx, key) (idx->dbi_hash(key) % idx->dbi_table->dbt_len)
136
137#define	ENQUEUE(head, l) { \
138	(l)->prev = NULL; \
139	(l)->next = (head); \
140	if ((l)->next) \
141	    (l)->next->prev = (l); \
142	(head) = (l); \
143}
144
145#define	DEQUEUE(head, l) { \
146	if ((l)->prev) \
147		(l)->prev->next = (l)->next; \
148	else \
149		(head) = (l)->next; \
150	if ((l)->next) \
151		(l)->next->prev = (l)->prev; \
152}
153
154#define	INVALIDATE_ADDR(a) ((a) = (void *)((unsigned long)(a) | 1L))
155#define	VALIDATE_ADDR(a) ((a) = (void *)((unsigned long)(a) & ~1L))
156#define	INVALID_ADDR(a) (((unsigned long)(a) & 1L))
157#define	INVALID_LINK(l) (INVALID_ADDR(l->entry))
158
159#define	ENQUEUE_IDX(bp, l) { \
160	rw_enter((bp)->dbk_lock, RW_WRITER); \
161	ENQUEUE((bp)->dbk_head, l); \
162	VALIDATE_ADDR((l)->entry); \
163	rw_exit((bp)->dbk_lock); \
164}
165
166#define	DEQUEUE_IDX(bp, l) { \
167	rw_enter((bp)->dbk_lock, RW_WRITER); \
168	INVALIDATE_ADDR((l)->entry); \
169	DEQUEUE((bp)->dbk_head, l); \
170	rw_exit((bp)->dbk_lock); \
171}
172
173#ifdef	__cplusplus
174}
175#endif
176
177#endif /* _NFS4_DB_IMPL_H */
178