xref: /illumos-gate/usr/src/cmd/isns/isnsd/cache.c (revision d52aae2365749461c362fde5a4c1a26a620cfbd3)
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 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #include "isns_server.h"
32 #include "isns_cache.h"
33 #include "isns_msgq.h"
34 #include "isns_obj.h"
35 #include "isns_htab.h"
36 
37 /*
38  * external variables
39  */
40 extern msg_queue_t *sys_q;
41 
42 #ifdef DEBUG
43 extern int verbose_lock;
44 #endif
45 
46 /*
47  * global data
48  */
49 int cache_flag = 0;
50 
51 /*
52  * local variables
53  */
54 static cache_t *imc;
55 
56 /*
57  * local functions.
58  */
59 
60 /*
61  * ****************************************************************************
62  * cache_init:
63  *	create the cache data initially, including to invoke individual
64  *	functions for creating the hash tables for object storage and
65  *	discovery domain membership matrix.
66  *
67  * return - 0: no error; 1: otherwise.
68  *
69  * ****************************************************************************
70  */
71 int
72 cache_init(void)
73 {
74 	/*
75 	 * allocate global cache memory.
76 	 */
77 	imc = (cache_t *)calloc(sizeof (cache_t), 1);
78 	if (imc == NULL ||
79 	    obj_tab_init(imc) != 0 ||
80 	    dd_matrix_init(imc) != 0) {
81 		cache_destroy();
82 		return (1); /* no memory */
83 	}
84 
85 	/*
86 	 * initialize global cache rwlock.
87 	 */
88 	(void) rwlock_init(&imc->l, USYNC_PROCESS, NULL);
89 
90 	/*
91 	 * inintialize global cache functions.
92 	 */
93 	imc->get_hval = obj_hval;
94 	imc->get_uid = get_obj_uid;
95 	imc->set_uid = set_obj_uid;
96 	imc->timestamp = get_timestamp;
97 	imc->add_hook = add_object;
98 	imc->replace_hook = replace_object;
99 	imc->cmp = obj_cmp;
100 	imc->clone = assoc_clone;
101 	imc->ddd = update_ddd;
102 #ifdef DEBUG
103 	imc->dump = obj_dump;
104 #endif
105 
106 	return (0);
107 }
108 
109 /*
110  * ****************************************************************************
111  * cache_destroy:
112  *	destroy the cache data.
113  *
114  * ****************************************************************************
115  */
116 void
117 cache_destroy(void)
118 {
119 	/* do nothing */
120 }
121 
122 /*
123  * ****************************************************************************
124  * cache_lock:
125  *	grab the lock on the cache data.
126  *
127  * mode - the read/write mode of the lock.
128  * return - error code.
129  *
130  * ****************************************************************************
131  */
132 int
133 cache_lock(int mode)
134 {
135 	int ret = 0;
136 
137 	switch (mode) {
138 	case CACHE_WRITE:
139 		ret = rw_wrlock(&imc->l);
140 #ifdef DEBUG
141 		if (verbose_lock) {
142 			printf("cache locked for writing.\n");
143 		}
144 #endif
145 		break;
146 	case CACHE_READ:
147 		ret = rw_rdlock(&imc->l);
148 #ifdef DEBUG
149 		if (verbose_lock) {
150 			printf("cache locked for reading.\n");
151 		}
152 #endif
153 		break;
154 	case CACHE_TRY_READ:
155 		ret = rw_tryrdlock(&imc->l);
156 #ifdef DEBUG
157 		if (verbose_lock) {
158 			if (ret == 0) {
159 				printf("cache locked for reading.\n");
160 			} else {
161 				printf("cache locked for reading failed.\n");
162 			}
163 		}
164 #endif
165 		break;
166 	default:
167 		break;
168 	}
169 
170 	return (ret);
171 }
172 
173 /*
174  * ****************************************************************************
175  * cache_unlock:
176  *	release the lock on the cache data.
177  *	if the cache was locked for writing, a synchronization between
178  *	the cache and persistent data store needs to be performed.
179  *
180  * mode - the read/write mode which the cache data was locked for.
181  * ec - 0: commit the cache update; otherwise retreat it.
182  * return - error code.
183  *
184  * ****************************************************************************
185  */
186 int
187 cache_unlock(int mode, int ec)
188 {
189 	if (mode != CACHE_NO_ACTION) {
190 		/* sync between cache and data store */
191 		if (mode == CACHE_WRITE) {
192 			if (sys_q) {
193 				ec = data_sync(ec);
194 			}
195 
196 			/* rest the cache update flag */
197 			RESET_CACHE_UPDATED();
198 		}
199 
200 		ASSERT(!IS_CACHE_UPDATED());
201 
202 		/* unlock it */
203 		(void) rw_unlock(&imc->l);
204 #ifdef DEBUG
205 		if (verbose_lock) {
206 			printf("cache unlocked.\n");
207 		}
208 #endif
209 	}
210 
211 	return (ec);
212 }
213 
214 /*
215  * ****************************************************************************
216  * cache_lock_read:
217  *	grab the read lock on the cache.
218  *
219  * return - error code.
220  *
221  * ****************************************************************************
222  */
223 int
224 cache_lock_read(void)
225 {
226 	return (cache_lock(CACHE_READ));
227 }
228 
229 /*
230  * ****************************************************************************
231  * cache_lock_write:
232  *	grab the write lock on the cache.
233  *
234  * return - error code.
235  *
236  * ****************************************************************************
237  */
238 int
239 cache_lock_write(void)
240 {
241 	return (cache_lock(CACHE_WRITE));
242 }
243 
244 /*
245  * ****************************************************************************
246  * cache_unlock_sync:
247  *	synchronize the cache with persistent data store and
248  *	release the lock.
249  *
250  * ec - 0: commit the cache update; otherwise retreat it.
251  * return - error code.
252  *
253  * ****************************************************************************
254  */
255 int
256 cache_unlock_sync(int ec)
257 {
258 	return (cache_unlock(CACHE_WRITE, ec));
259 }
260 
261 /*
262  * ****************************************************************************
263  * cache_unlock_nosync:
264  *	release the lock, no need to sync the data between cache and
265  *	data store.
266  *	if the cache has been updated, do not call this function, call
267  *	cache_unlock_sync() with non-zero error code to indicate the
268  *	sync action.
269  *
270  * return - error code.
271  *
272  * ****************************************************************************
273  */
274 int
275 cache_unlock_nosync(void)
276 {
277 	return (cache_unlock(CACHE_READ, 0));
278 }
279 
280 /*
281  * ****************************************************************************
282  * cache_get_htab:
283  *	get the hash table for individual type of object.
284  *
285  * type - the object type.
286  * return - the hash table.
287  *
288  * ****************************************************************************
289  */
290 htab_t *
291 cache_get_htab(isns_type_t type)
292 {
293 	if (type > 0 && type < MAX_OBJ_TYPE) {
294 		return (imc->t[type]);
295 	}
296 
297 	return (NULL);
298 }
299 
300 /*
301  * ****************************************************************************
302  * cache_get_matrix:
303  *	get the membership matrix for a discovery domain or a
304  *	discovery domain set.
305  *
306  * type - the discovery domain or discovery domain set object type.
307  * return - the matrix.
308  *
309  * ****************************************************************************
310  */
311 matrix_t *
312 cache_get_matrix(isns_type_t type)
313 {
314 	matrix_t *x = NULL;
315 
316 	switch (type) {
317 	case OBJ_DD:
318 		x = imc->x[0];
319 		break;
320 	case OBJ_DDS:
321 		x = imc->x[1];
322 		break;
323 	default:
324 		break;
325 	}
326 
327 	return (x);
328 }
329 
330 /*
331  * ****************************************************************************
332  * cache_lookup:
333  *	invoke the hash table lookup for looking up a specific object and
334  *	perform the callback function on the object.
335  *
336  * lcp - the object lookup control data.
337  * uid_p - the pointer of object UID for returning.
338  * callback - the callback function for the object.
339  * return - error code.
340  *
341  * ****************************************************************************
342  */
343 int
344 cache_lookup(lookup_ctrl_t *lcp, uint32_t *uid_p,
345     int (*callback)(void *, void *))
346 {
347 	return (htab_lookup(imc->t[lcp->type],
348 	    lcp,
349 	    (lcp->op[0] == OP_INTEGER) ? lcp->data[0].ui : 0,
350 	    uid_p,
351 	    callback,
352 	    0));
353 }
354 
355 /*
356  * ****************************************************************************
357  * cache_lookup:
358  *	invoke the hash table lookup for looking up a specific object,
359  *	the callback function is going to change the key of the object.
360  *
361  * lcp - the object lookup control data.
362  * uid_p - the pointer of object UID for returning.
363  * callback - the callback function for the object.
364  * return - error code.
365  *
366  * ****************************************************************************
367  */
368 int
369 cache_rekey(lookup_ctrl_t *lcp, uint32_t *uid_p,
370     int (*callback)(void *, void *))
371 {
372 	return (htab_lookup(imc->t[lcp->type],
373 	    lcp,
374 	    (lcp->op[0] == OP_INTEGER) ? lcp->data[0].ui : 0,
375 	    uid_p,
376 	    callback,
377 	    1));
378 }
379 
380 /*
381  * ****************************************************************************
382  * cache_add:
383  *	invoke hash table add to add an object.
384  *
385  * obj - the object being added.
386  * flag - 0: a real object;
387  *	  otherwise an association object for discovery domain membership.
388  * uid_p - the pointer of object UID for returning.
389  * update_p - the pointer of flag (update object or newly register)
390  *		for returning.
391  * return - error code.
392  *
393  * ****************************************************************************
394  */
395 int
396 cache_add(isns_obj_t *obj, int flag, uint32_t *uid_p, int *update_p)
397 {
398 	return (htab_add(imc->t[obj->type], obj, flag, uid_p, update_p));
399 }
400 
401 /*
402  * ****************************************************************************
403  * cache_remove:
404  *	invoke hash table remove to remove an object.
405  *
406  * lcp - the lookup control data for the object being removed.
407  * flag - 0: a real object;
408  *	  otherwise an association object for discovery domain membership.
409  * return - the removed object.
410  *
411  * ****************************************************************************
412  */
413 isns_obj_t *
414 cache_remove(lookup_ctrl_t *lcp, int flag)
415 {
416 	return (htab_remove(imc->t[lcp->type],
417 	    lcp,
418 	    (lcp->op[0] == OP_INTEGER) ? lcp->data[0].ui : 0,
419 	    flag));
420 }
421 
422 /*
423  * ****************************************************************************
424  * cache_dump_htab:
425  *	dump the hash table for debugging purpose.
426  *
427  * type - the object type.
428  *
429  * ****************************************************************************
430  */
431 #ifdef DEBUG
432 void
433 cache_dump_htab(isns_type_t type)
434 {
435 	(void) htab_dump(imc->t[type]);
436 }
437 #endif
438