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