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(void)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
cache_destroy(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
cache_lock(int mode)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
cache_unlock(int mode,int ec)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
cache_lock_read(void)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
cache_lock_write(void)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
cache_unlock_sync(int ec)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
cache_unlock_nosync(void)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 *
cache_get_htab(isns_type_t type)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 *
cache_get_matrix(isns_type_t type)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
cache_lookup(lookup_ctrl_t * lcp,uint32_t * uid_p,int (* callback)(void *,void *))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
cache_rekey(lookup_ctrl_t * lcp,uint32_t * uid_p,int (* callback)(void *,void *))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
cache_add(isns_obj_t * obj,int flag,uint32_t * uid_p,int * update_p)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 *
cache_remove(lookup_ctrl_t * lcp,int flag)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
cache_dump_htab(isns_type_t type)433 cache_dump_htab(isns_type_t type)
434 {
435 (void) htab_dump(imc->t[type]);
436 }
437 #endif
438