main.c revision 3f1da666124ac25caadfacd3f2a361d4a41268a8
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <pthread.h>
#include <errno.h>
#include <libscf.h>
#ifdef DEBUG
#include <time.h>
#endif
#include <signal.h>
#include <semaphore.h>
#include "isns_server.h"
#include "isns_dseng.h"
#include "isns_msgq.h"
#include "isns_log.h"
#include "isns_cfg.h"
#include "isns_utils.h"
#include "isns_cache.h"
#include "isns_obj.h"
#include "isns_dd.h"
#include "isns_scn.h"
#include "isns_sched.h"
#include "isns_esi.h"
#include "isns_mgmt.h"
/*
* iSNS Server administrative settings.
*/
uint8_t daemonlize = 0;
int dbg_level = 7;
char data_store[MAXPATHLEN];
/* semaphore for handling exit */
static sem_t isns_child_sem;
static int isns_child_smf_exit_code;
static pid_t isns_child_pid;
#if !defined(SMF_EXIT_ERR_OTHER)
#define SMF_EXIT_ERR_OTHER -1
#endif
/*
* Globals for singal handling. time_to_exit is set by sig_handle()
* when set the main thread(daemon) and othere threads should exit.
*
* semaphone is used to make sure all threads that are created
* by isns_port_watcher and esi.
*/
static uint32_t thr_ref_count;
/*
* Door creation flag.
*/
/*
* global system message queue
*/
#ifdef DEBUG
extern dump_db(void);
#endif
extern void sigalrm(int);
/*
* sigusr2_handler -- SIGUSR2 Handler
* sigusr2 is exepected only when child is running okay.
*/
/* ARGSUSED */
static void
int sig
)
{
/* post okay status. */
"SIGUSR@ is received. Parent is existing...");
(void) sem_post(&isns_child_sem);
}
/*
* sigchld_handler -- SIGCHLD Handler
* sigchld is exepected only when there is an error.
*/
/* ARGSUSED */
static void
int sig
)
{
int status;
/* This is the default code. */
if (ret_pid == isns_child_pid) {
}
}
(void) sem_post(&isns_child_sem);
}
/* ARGSUSED */
static void
int sig
)
{
"SIGHUP is received. Reloading config...");
}
/* ARGSUSED */
static void
int sig
)
{
"Signal: %d received and sending server exit.", sig);
}
void
)
{
(void) pthread_mutex_lock(&thr_count_mtx);
"increase thread reference count(%d).", thr_ref_count);
(void) pthread_mutex_unlock(&thr_count_mtx);
}
void
)
{
(void) pthread_mutex_lock(&thr_count_mtx);
"decrease thread reference count(%d).", thr_ref_count);
(void) pthread_mutex_unlock(&thr_count_mtx);
}
)
{
(void) pthread_mutex_lock(&thr_count_mtx);
ref = thr_ref_count;
(void) pthread_mutex_unlock(&thr_count_mtx);
"checking thread reference count %d.", ref);
return (ref);
}
void
)
{
}
int
main(
/* LINTED E_FUNC_ARG_UNUSED */
int argc,
/* LINTED E_FUNC_ARG_UNUSED */
char *argv[]
)
{
int opt_i = 0;
int i;
#ifdef DEBUG
time_t t;
clock_t c;
#endif
#ifdef DEBUG
}
#endif
/* set locale */
/* load administative settings. pick up data location. */
if (load_config(B_TRUE) != 0) {
}
/* A signal handler is set for SIGCHLD. */
#ifdef DEBUG
printf("start daemon\n");
#endif
if (opt_i == 0 || daemonlize) {
daemonlize = 1;
/* daemonlize */
isns_child_pid = fork();
if (isns_child_pid < 0) {
/*
* cannot fork(), terminate the server.
*/
}
if (isns_child_pid > 0) {
/*
* terminate parent.
*/
(void) sem_wait(&isns_child_sem);
(void) sem_destroy(&isns_child_sem);
}
/*
*/
(void) dup2(i, 1);
(void) dup2(i, 2);
} /* end of daemonlize */
#ifdef DEBUG
printf("calling cache init\n");
#endif
/* initialize object hash table */
if (cache_init() != 0) {
"object hash table initialization error.");
}
/* initialize event list */
"ESI event list initialization error.");
}
/* initialize iSNS database */
if (init_data() != 0) {
"internal database initialization error");
}
#ifdef DEBUG
printf("calling load_data\n");
c = clock();
#endif
if (load_data() != 0) {
}
#ifdef DEBUG
c = clock() - c;
printf("time %d clock %.4lf -loading data\n",
t, c / (double)CLOCKS_PER_SEC);
#endif
#ifdef DEBUG
printf("sys queue creating...\n");
#endif
/* create a message queue for system control */
sys_q = queue_calloc();
if (!sys_q) {
}
/* create a message queue for scn thread */
scn_q = queue_calloc();
if (!scn_q) {
}
/* create scn thread */
/* create them if they are not there. */
if (verify_ddd() != 0) {
}
/* setup and verify the portal(s) for scn(s) */
/* after scn registry is loaded from data store. */
if (verify_scn_portal() != 0) {
}
/* setup and verify the portal(s) for esi(s) */
/* after esi list is loaded from data store. */
if (verify_esi_portal() != 0) {
}
#ifdef DEBUG
printf("scn queue creating...\n");
#endif
/* create scn thread */
}
/* setup a door for management interface */
if (setup_mgmt_door(sys_q) != 0) {
}
/* create server port watcher */
isns_port_watcher, (void *)sys_q) != 0) {
}
/* create entity status inquiry thread */
}
#ifdef DEBUG
if (!daemonlize) {
(void) pthread_create(&tid,
NULL,
(void *)sys_q);
}
#endif
if (opt_i == 0 || daemonlize) {
getppid());
}
/* pause */
for (;;) {
case DATA_ADD:
case DATA_UPDATE:
case DATA_DELETE:
case DATA_DELETE_ASSOC:
case DATA_COMMIT:
case DATA_RETREAT:
break;
case REG_EXP:
/* registration expiring */
break;
case DEAD_PORTAL:
break;
case SERVER_EXIT:
/* graceful exit. */
(void) queue_msg_free(msg);
"wake up ESI and stop it.");
(void) get_stopwatch(1);
"sending SCN stop msg.");
if (door_created) {
"closing the door.");
(void) fdetach(ISNS_DOOR_NAME);
}
"esi thread %d exited.", esi_tid);
"port watcher thread %d exited.", port_tid);
"scn thread %d exited.", scn_tid);
/* now check any remaining threads. */
i = 0;
do {
thr_cnt = get_thr_count();
if (thr_cnt == 0) {
"main thread %d is done.",
pthread_self());
exit(1);
} else {
(void) sleep(1);
i++;
}
} while (MAX_RETRY_COUNT > i);
"main thread %d existing ...",
pthread_self());
exit(1);
break;
case CONFIG_RELOAD:
/* load config again. don't pick data store. */
(void) load_config(B_FALSE);
break;
case SYS_QUIT_OK:
(void) queue_msg_free(msg);
exit(0);
default:
break;
}
(void) queue_msg_free(msg);
}
/* LINTED E_STMT_NOT_REACHED */
return (0);
}