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.
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.
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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <sys/types.h>
40 #include <semaphore.h>
43 #include "isns_server.h"
44 #include "isns_dseng.h"
45 #include "isns_msgq.h"
48 #include "isns_utils.h"
49 #include "isns_cache.h"
53 #include "isns_sched.h"
55 #include "isns_mgmt.h"
58 * iSNS Server administrative settings.
60 uint8_t daemonlize
= 0;
62 uint64_t esi_threshold
;
64 ctrl_node_t
*control_nodes
= NULL
;
65 pthread_mutex_t ctrl_node_mtx
= PTHREAD_MUTEX_INITIALIZER
;
66 char data_store
[MAXPATHLEN
];
69 /* semaphore for handling exit */
70 static sem_t isns_child_sem
;
71 static int isns_child_smf_exit_code
;
72 static pid_t isns_child_pid
;
74 #if !defined(SMF_EXIT_ERR_OTHER)
75 #define SMF_EXIT_ERR_OTHER -1
79 * Globals for singal handling. time_to_exit is set by sig_handle()
80 * when set the main thread(daemon) and othere threads should exit.
82 * semaphone is used to make sure all threads that are created
83 * by isns_port_watcher and esi.
85 boolean_t time_to_exit
= B_FALSE
;
86 static uint32_t thr_ref_count
;
87 static pthread_mutex_t thr_count_mtx
= PTHREAD_MUTEX_INITIALIZER
;
88 #define MAX_RETRY_COUNT 10 /* for checking remaining threads before exit. */
93 boolean_t door_created
= B_FALSE
;
96 * global system message queue
98 msg_queue_t
*sys_q
= NULL
;
99 msg_queue_t
*scn_q
= NULL
;
102 extern void *cli_test(void *argv
);
103 extern dump_db(void);
106 extern void sigalrm(int);
109 * sigusr2_handler -- SIGUSR2 Handler
110 * sigusr2 is exepected only when child is running okay.
118 /* post okay status. */
119 isnslog(LOG_DEBUG
, "sigusr2_handler",
120 "SIGUSR@ is received. Parent is existing...");
121 isns_child_smf_exit_code
= SMF_EXIT_OK
;
123 (void) sem_post(&isns_child_sem
);
127 * sigchld_handler -- SIGCHLD Handler
128 * sigchld is exepected only when there is an error.
139 /* This is the default code. */
140 isns_child_smf_exit_code
= SMF_EXIT_ERR_OTHER
;
142 ret_pid
= waitpid(isns_child_pid
, &status
, WNOHANG
);
144 if (ret_pid
== isns_child_pid
) {
145 if (WIFEXITED(status
)) {
146 isns_child_smf_exit_code
= WEXITSTATUS(status
);
149 (void) sem_post(&isns_child_sem
);
159 isnslog(LOG_DEBUG
, "sighup_handle",
160 "SIGHUP is received. Reloading config...");
161 (void) queue_msg_set(sys_q
, CONFIG_RELOAD
, NULL
);
170 isnslog(LOG_DEBUG
, "sigexit_handler",
171 "Signal: %d received and sending server exit.", sig
);
179 (void) pthread_mutex_lock(&thr_count_mtx
);
181 isnslog(LOG_DEBUG
, "inc_thr_count",
182 "increase thread reference count(%d).", thr_ref_count
);
186 (void) pthread_mutex_unlock(&thr_count_mtx
);
193 (void) pthread_mutex_lock(&thr_count_mtx
);
195 isnslog(LOG_DEBUG
, "dec_thr_count",
196 "decrease thread reference count(%d).", thr_ref_count
);
200 (void) pthread_mutex_unlock(&thr_count_mtx
);
209 (void) pthread_mutex_lock(&thr_count_mtx
);
213 (void) pthread_mutex_unlock(&thr_count_mtx
);
215 isnslog(LOG_DEBUG
, "get_thr_count",
216 "checking thread reference count %d.", ref
);
225 isnslog(LOG_DEBUG
, "shutdown", "raise exit flag.");
226 time_to_exit
= B_TRUE
;
227 (void) queue_msg_set(sys_q
, SERVER_EXIT
, NULL
);
232 /* LINTED E_FUNC_ARG_UNUSED */
234 /* LINTED E_FUNC_ARG_UNUSED */
239 pthread_t port_tid
, esi_tid
, scn_tid
;
249 if (getopt(argc
, argv
, "i") == 'i') {
250 opt_i
= 1; /* interactive mode */
255 openlog(ISNS_DAEMON_SYSLOG_PP
, LOG_PID
| LOG_CONS
, LOG_DAEMON
);
257 /* load administative settings. pick up data location. */
258 if (load_config(B_TRUE
) != 0) {
259 isnslog(LOG_ERR
, "main", "administrative settings load error.");
260 exit(SMF_EXIT_ERR_OTHER
);
263 /* A signal handler is set for SIGCHLD. */
264 (void) signal(SIGCHLD
, sigchld_handler
);
265 (void) signal(SIGUSR2
, sigusr2_handler
);
266 (void) sigset(SIGALRM
, sigalrm
);
269 printf("start daemon\n");
271 if (opt_i
== 0 || daemonlize
) {
272 isnslog(LOG_DEBUG
, "main", "now forking... pid %d", getpid());
275 isns_child_pid
= fork();
276 if (isns_child_pid
< 0) {
278 * cannot fork(), terminate the server.
280 exit(SMF_EXIT_ERR_CONFIG
);
282 if (isns_child_pid
> 0) {
286 (void) sem_wait(&isns_child_sem
);
287 (void) sem_destroy(&isns_child_sem
);
288 isnslog(LOG_DEBUG
, "main", "exiting with %d",
289 isns_child_smf_exit_code
);
290 exit(isns_child_smf_exit_code
);
294 * redirect stdout, and stderr to /dev/null.
296 i
= open("/dev/null", O_RDWR
);
299 } /* end of daemonlize */
302 printf("calling cache init\n");
304 /* initialize object hash table */
305 if (cache_init() != 0) {
306 isnslog(LOG_ERR
, "main",
307 "object hash table initialization error.");
308 exit(SMF_EXIT_ERR_OTHER
);
311 /* initialize event list */
312 if (el_init(10, 60, 6) != 0) {
313 isnslog(LOG_ERR
, "main",
314 "ESI event list initialization error.");
315 exit(SMF_EXIT_ERR_OTHER
);
318 /* initialize iSNS database */
319 if (init_data() != 0) {
320 isnslog(LOG_ERR
, "main",
321 "internal database initialization error");
322 exit(SMF_EXIT_ERR_OTHER
);
326 printf("calling load_data\n");
331 if (load_data() != 0) {
332 isnslog(LOG_ERR
, "main", "loading data store failed");
333 exit(SMF_EXIT_ERR_OTHER
);
339 printf("time %d clock %.4lf -loading data\n",
340 t
, c
/ (double)CLOCKS_PER_SEC
);
344 printf("sys queue creating...\n");
346 /* create a message queue for system control */
347 sys_q
= queue_calloc();
349 exit(SMF_EXIT_ERR_OTHER
);
352 /* create a message queue for scn thread */
353 scn_q
= queue_calloc();
355 exit(SMF_EXIT_ERR_OTHER
);
358 /* create scn thread */
359 /* Check for Default DD/DD-set existence and */
360 /* create them if they are not there. */
361 if (verify_ddd() != 0) {
362 exit(SMF_EXIT_ERR_OTHER
);
365 /* setup and verify the portal(s) for scn(s) */
366 /* after scn registry is loaded from data store. */
367 if (verify_scn_portal() != 0) {
368 exit(SMF_EXIT_ERR_OTHER
);
371 /* setup and verify the portal(s) for esi(s) */
372 /* after esi list is loaded from data store. */
373 if (verify_esi_portal() != 0) {
374 exit(SMF_EXIT_ERR_OTHER
);
378 printf("scn queue creating...\n");
381 (void) sigset(SIGHUP
, sighup_handler
);
382 (void) sigset(SIGINT
, sigexit_handler
);
383 (void) sigset(SIGTERM
, sigexit_handler
);
384 (void) sigset(SIGQUIT
, sigexit_handler
);
386 /* create scn thread */
387 if (pthread_create(&scn_tid
, NULL
, scn_proc
, NULL
) != 0) {
388 isnslog(LOG_ERR
, "main", "SCN thread creating error.");
389 exit(SMF_EXIT_ERR_OTHER
);
392 /* setup a door for management interface */
393 if (setup_mgmt_door(sys_q
) != 0) {
394 exit(SMF_EXIT_ERR_OTHER
);
397 /* create server port watcher */
398 if (pthread_create(&port_tid
, NULL
,
399 isns_port_watcher
, (void *)sys_q
) != 0) {
400 isnslog(LOG_ERR
, "main", "iSNS port thread creating error.");
401 exit(SMF_EXIT_ERR_OTHER
);
404 /* create entity status inquiry thread */
405 if (pthread_create(&esi_tid
, NULL
,
406 esi_proc
, NULL
) != 0) {
407 isnslog(LOG_ERR
, "main", "ESI thread creating error.");
408 exit(SMF_EXIT_ERR_OTHER
);
413 (void) pthread_create(&tid
,
419 if (opt_i
== 0 || daemonlize
) {
420 isnslog(LOG_DEBUG
, "main", "issuing SIGUSR2.. parent pid %d",
422 (void) kill(getppid(), SIGUSR2
);
427 msg_text_t
*msg
= queue_msg_get(sys_q
);
432 case DATA_DELETE_ASSOC
:
437 /* registration expiring */
438 reg_expiring(msg
->data
);
441 portal_dies((uint32_t)msg
->data
);
445 (void) queue_msg_free(msg
);
446 isnslog(LOG_DEBUG
, "main",
447 "wake up ESI and stop it.");
448 (void) get_stopwatch(1);
449 isnslog(LOG_DEBUG
, "main",
450 "sending SCN stop msg.");
451 (void) queue_msg_set(scn_q
, SCN_STOP
, NULL
);
453 isnslog(LOG_DEBUG
, "main",
454 "closing the door.");
455 (void) fdetach(ISNS_DOOR_NAME
);
457 (void) pthread_join(esi_tid
, NULL
);
458 isnslog(LOG_DEBUG
, "main",
459 "esi thread %d exited.", esi_tid
);
460 (void) pthread_join(port_tid
, NULL
);
461 isnslog(LOG_DEBUG
, "main",
462 "port watcher thread %d exited.", port_tid
);
463 (void) pthread_join(scn_tid
, NULL
);
464 isnslog(LOG_DEBUG
, "main",
465 "scn thread %d exited.", scn_tid
);
467 /* now check any remaining threads. */
470 thr_cnt
= get_thr_count();
472 isnslog(LOG_DEBUG
, "main",
473 "main thread %d is done.",
480 } while (MAX_RETRY_COUNT
> i
);
481 isnslog(LOG_DEBUG
, "main",
482 "main thread %d existing ...",
487 /* load config again. don't pick data store. */
488 (void) load_config(B_FALSE
);
491 (void) queue_msg_free(msg
);
496 (void) queue_msg_free(msg
);
499 /* LINTED E_STMT_NOT_REACHED */