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
cache_init()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
cache_destroy()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
cache_lock(int mode)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
cache_unlock(int mode,int ec)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
cache_lock_read()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
cache_lock_write()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
cache_unlock_sync(int ec)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
cache_unlock_nosync()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 *
cache_get_htab(isns_type_t type)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 *
cache_get_matrix(isns_type_t type)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
cache_lookup(lookup_ctrl_t * lcp,uint32_t * uid_p,int (* callback)(void *,void *))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
cache_rekey(lookup_ctrl_t * lcp,uint32_t * uid_p,int (* callback)(void *,void *))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
cache_add(isns_obj_t * obj,int flag,uint32_t * uid_p,int * update_p)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 *
cache_remove(lookup_ctrl_t * lcp,int flag)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
cache_dump_htab(isns_type_t type)463 cache_dump_htab(
464 isns_type_t type
465 )
466 {
467 (void) htab_dump(imc->t[type]);
468 }
469 #endif
470