#pragma module NNTP_MAIN "DNNTP/OVMS 2-C" /* **++ ** FACILITY: NNTP Server for OpenVMS ** ** MODULE DESCRIPTION: ** ** A main module of theNNTP server. ** ** AUTHORS: ** ** Copyright (c) 1996-2006 Ruslan R. Laishev ** ** CREATION DATE: ??-???-1996 ** ** ** MODIFICATION HISTORY: ** ** 6-FEB-2002 RRL Changed scheduling of start an purging task, ** increased a thread stack size 32000->64000 bytes. ** 10-FEB-2002 RRL Redesign a waiting of purging event. ** 15-FEB-2006 RRL Added SHUTDOWN from NNTPCP. ** ** {@tbs@}... **-- */ /* ** ** INCLUDE FILES ** */ #include #include #include #include #include #include "nntp.h" char *ID$IDcpy = "Copyright (c) 1996-2006,Ruslan R. Laishev (@RRL)."; char *ID$IDsrv = "DNNTP/OVMS 2-B"; char *ID$IDver = "DECThreads NNTP Server for OpenVMS Ver. 2-C, OpenVMS/"\ VMS_VERSION; pthread_attr_t tattr; int purging_enable = 0, exit_flag = 0; $DESCRIPTOR(res_dsc,"NNTP_SRV$SHUT"); /* **++ ** FUNCTIONAL DESCRIPTION: ** ** Blocking AST procedure, just set the global exit flag, and wakeup a main thread. ** ** FORMAL PARAMETERS: ** ** None. ** ** RETURN VALUE: ** ** None. ** **-- */ void blocking_AST (void) { /* ** Set global exit flag, and call $WAKE to wake-up a main ** thread has been blocked by sys$hiber() */ exit_flag = 1; sys$wake(0,0); } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** Timer AST procedure called at timer expiration time. Set a special flag (purging can be started) ** and wake uping a main thread. ** ** FORMAL PARAMETERS: ** ** None. ** ** RETURN VALUE: ** ** VMS condition code ** **-- */ int purging_AST ( void *arg ) { /* ** Set purging enable flag to nonzero value and wake up the process */ return purging_enable = sys$wake(0,0); } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** The server initialization. ** ** FORMAL PARAMETERS: ** ** None. ** ** RETURN VALUE: ** ** VMS condition code ** **-- */ int main (void) { int status,tomorrow_bin[2]; pthread_t th0,th1,th2; $DESCRIPTOR(tomorrow_dsc,"TOMORROW"); lksb lksb_; NNTP_LOG(LOG$K_INF,ID$IDcpy); NNTP_LOG(LOG$K_INF,ID$IDver); /* ** */ NNTP_LOG(LOG$K_INF,"Get configuration information."); if ( !(1 & (status = nntp_conf_get())) ) sys$exit(status); nntp_conf_out(); /* ** */ NNTP_LOG(LOG$K_INF,"Opening News Messages DataBase"); if ( !(1 & (status = MsgDBopen())) ) sys$exit(status); NNTP_LOG(LOG$K_INF,"Opening NewsGroups DataBase"); if ( !(1 & (status = GrpDBopen())) ) sys$exit(status); NNTP_LOG(LOG$K_INF,"Opening Feed and Suck DataBase"); if ( !(1 & (status = FeedSuckDBopen())) ) sys$exit(status); /* ** Some specific DECThreads initialization */ decc$set_reentrancy(C$C_MULTITHREAD); #ifdef __VAX pthread_attr_create(&tattr); pthread_attr_setstacksize(&tattr,64000); #else pthread_attr_init(&tattr); pthread_attr_setdetachstate(&tattr,PTHREAD_CREATE_DETACHED); pthread_attr_setstacksize(&tattr,64000); #endif NNTP_InitBosses (); /* ** */ if ( 0 > (status = pthread_create(&th0,&tattr,NNTP_ClientBoss,NULL)) ) { NNTP_LOG(LOG$K_FAT,"Create Client Boss thread-%s.", strerror(status)); } NNTP_LOG(LOG$K_INF,"Create Client Boss thread-Ok (Tid:0%xh).",th0); /* ** Start an incomming connections listener */ if (0 > (status = pthread_create(&th1,&tattr,NNTP_SuckBoss,NULL)) ) { NNTP_LOG(LOG$K_FAT,"Create Suck Boss thread-%s.", strerror(status)); } NNTP_LOG(LOG$K_INF,"Create Suck Boss thread-Ok (Tid:0%xh).",th1); /* ** Start a feed thread */ if ( 0 > (status = pthread_create(&th2,&tattr,NNTP_FeedBoss,NULL)) ) { NNTP_LOG(LOG$K_FAT,"Create Feed Boss thread-%s.", strerror(status)); } NNTP_LOG(LOG$K_INF,"Create Feed Boss thread-Ok (Tid:0%xh).",th2); /* ** Queue a lock request, to watching a SHUTDOWN Request */ if ( !(1 & (status = sys$enqw (EFN$C_ENF, LCK$K_CRMODE, &lksb_, LCK$M_SYSTEM,&res_dsc,0,0,0,blocking_AST,0,0,0))) || !(1 & (lksb_.lksb$w_status)) ) return (1 & status)?lksb_.lksb$w_status:status; /* ** Main loop */ while ( !exit_flag ) { NNTP_LOG(LOG$K_INF,"Schedule of database purging thread at midnight."); /* ** Convert a time to VMS binary format */ if ( !(1 & (status = lib$convert_date_string(&tomorrow_dsc,tomorrow_bin))) ) sys$exit(status); /* ** Clear purging enable flag */ purging_enable = 0; /* ** Enqueue a timer request */ if ( !(1 & (status = sys$setimr(0,tomorrow_bin,purging_AST,&status,0))) ) lib$signal(status); /* ** Start sleeping until tomorrow, we use loop and purging_enable checking ** to prevent unexpected hibernation under DECThreads environment. */ while ( (!purging_enable) && (!exit_flag) ) { if ( (!exit_flag) && (!(1 & (status = sys$hiber()))) ) lib$signal(status); } /* ** Start Database purging task */ if ( !exit_flag ) { NNTP_LOG(LOG$K_INF,"Beging of database purging task."); NNTP_ExpireBoss(); NNTP_LOG(LOG$K_INF,"End of database purging task."); } } NNTP_LOG(LOG$K_INF,"Got SHUTDOWN Signal."); sys$deq(lksb_.lksb$l_lkid,0,0,0); DBclose(); NNTP_LOG(LOG$K_INF,"%s-End.",ID$IDver); }