diff src/server.c @ 149:bfeea2bc09b6 noffle

[svn] Output to buffer, release lock and then send output.
author bears
date Thu, 26 Oct 2000 22:13:28 +0100
parents 8b9366fc1361
children 22b81617d427
line wrap: on
line diff
--- a/src/server.c	Sun Oct 15 18:30:19 2000 +0100
+++ b/src/server.c	Thu Oct 26 22:13:28 2000 +0100
@@ -1,7 +1,7 @@
 /*
   server.c
 
-  $Id: server.c 217 2000-09-23 10:40:35Z enz $
+  $Id: server.c 225 2000-10-26 21:13:28Z bears $
 */
 
 #if HAVE_CONFIG_H
@@ -55,8 +55,9 @@
     time_t lastServerOpen;
     int artPtr;
     Str grp; /* selected group, "" if none */
-    Bool readAlarmFlag;
-} server = { FALSE, 0L, 0, "", FALSE };
+    DynStr *reply;
+    Bool eotAfterReply;
+} server = { FALSE, 0L, 0, "", NULL, FALSE };
 
 typedef struct Cmd
 {
@@ -172,8 +173,8 @@
     vsnprintf( s, MAXCHAR, fmt, ap );
     va_end( ap );
     snprintf( line, MAXCHAR, "%u %s", stat, s );
+    DynStr_appLn( server.reply, line );    
     Log_dbg( "[S] %s", line );
-    printf( "%s\r\n", line );
 }
 
 static void
@@ -185,20 +186,20 @@
     va_start( ap, fmt );
     vsnprintf( line, MAXCHAR, fmt, ap );
     va_end( ap );
-    Prt_putTxtLn( line, stdout );
+    DynStr_appLn( server.reply, line );
 }
 
 static void
 putTxtBuf( const char *buf )
 {
     if ( buf )
-        Prt_putTxtBuf( buf, stdout );
+	DynStr_app( server.reply, buf );
 }
 
 static void
 putEndOfTxt( void )
 {
-    Prt_putEndOfTxt( stdout );
+    server.eotAfterReply = TRUE;
 }
 
 static void
@@ -208,65 +209,21 @@
 }
 
 static void
-readAlarm( int sig )
-{
-    UNUSED( sig );
-
-    server.readAlarmFlag = TRUE;
-    return;
-}
-
-static sig_t
-installSignalHandler( int sig, sig_t handler )
+initOutput( void )
 {
-    struct sigaction act, oldAct;
-
-    act.sa_handler = handler;
-    sigemptyset( &act.sa_mask );
-    act.sa_flags = 0;
-    if ( sig != SIGALRM )
-        act.sa_flags |= SA_RESTART;
-    if ( sigaction( sig, &act, &oldAct ) < 0 )
-        return SIG_ERR;
-    return oldAct.sa_handler;
+    server.reply = new_DynStr( 100 );
+    server.eotAfterReply = FALSE;
 }
 
-/*
- * Returns: < 0 on error, 0 on timeout, > 0 on success.
- * If timeout is zero, wait indefinitely.
- */
-static int
-waitCmdLn( Str line, int timeoutSeconds )
+static void
+sendOutput( void )
 {
-    sig_t oldHandler;
-    int r;
-
-    ASSERT( timeoutSeconds >= 0 );
-
-    /* Special case - no timeout. */
-    if ( timeoutSeconds == 0 )
-    {
-	r = Prt_getLn( line, stdin, -1 );
-	return ( r ) ? 1 : -1;
-    }
-
-    server.readAlarmFlag = FALSE;
-    oldHandler = installSignalHandler( SIGALRM, readAlarm );
-    if ( oldHandler == SIG_ERR )
-    {
-        Log_err( "client.c:connectWithTimeout: signal failed." );
-        return -1;
-    }
-    if ( alarm( ( unsigned int ) timeoutSeconds ) != 0 )
-        Log_err( "server.c:waitCmdLn: Alarm was already set." );
-    r = Prt_getLn( line, stdin, -1 );
-    alarm( 0 );
-    installSignalHandler( SIGALRM, oldHandler );
-    if ( server.readAlarmFlag )
-        return 0;
-    else if ( r )
-        return 1;
-    return -1;
+    Prt_putTxtBuf( DynStr_str( server.reply ), stdout );
+    if ( server.eotAfterReply )
+	Prt_putEndOfTxt( stdout );
+    fflush( stdout );
+    Log_dbg( "[S FLUSH]" );
+    del_DynStr( server.reply );
 }
 
 static Bool
@@ -699,14 +656,11 @@
     const char *g;
 
     putStat( STAT_GRPS_FOLLOW, "Groups" );
-    fflush( stdout );
-    Log_dbg( "[S FLUSH]" );
     if ( Grp_exists( pat ) )
     {
         (*printProc)( line, pat );
-        if ( ! Prt_putTxtLn( line, stdout ) )
-            Log_err( "Writing to stdout failed." );
-    }                    
+	putTxtLn( line );
+    }
     else
     {
 	if ( Grp_firstGrp( &g ) )
@@ -714,8 +668,7 @@
 		if ( Wld_match( g, pat ) )
 		{
 		    (*printProc)( line, g );
-		    if ( ! Prt_putTxtLn( line, stdout ) )
-			Log_err( "Writing to stdout failed." );
+		    putTxtLn( line );
 		}
 	    while ( Grp_nextGrp( &g ) );
     }
@@ -844,14 +797,6 @@
     else
     {
         changeToGrp( arg );
-
-	/*
-	 * The output may take some time, so release the lock
-	 * while outputting (all the required data is in RAM
-	 * at this point).
-	 */
-	closeServer();
-	
         first = Cont_first();
         last = Cont_last();
         putStat( STAT_GRP_SELECTED, "Article list" );
@@ -1015,22 +960,20 @@
     UNUSED(arg);
     UNUSED(cmd);
     
-    putStat( STAT_SEND_ART, "Continue (end with period)" );
-    fflush( stdout );
-    Log_dbg( "[S FLUSH]" );
-    s = new_DynStr( 10000 );
-	
-    
     /*
      * The article may take some time coming in, so release the
      * lock while collecting it.
      */
+    putStat( STAT_SEND_ART, "Continue (end with period)" );
+    sendOutput();
     closeServer();
     
+    s = new_DynStr( 10000 );
     err = FALSE;
     while ( ! err && getTxtLn( line, &err ) )
 	DynStr_appLn( s, line );
 
+    initOutput();
     if ( ! initServer() )
     {
 	del_DynStr( s );
@@ -1038,7 +981,7 @@
     }
 
     if ( ! err
-	 && Post_open( DynStr_str( s ) )
+	 && Post_open( DynStr_str( s ), 0 )
 	 && Post_post() )
     {
         putStat( STAT_POST_OK, "Message posted" );
@@ -1350,15 +1293,6 @@
     
     if ( ! testGrpSelected() )
         return TRUE;
-    Grp_setLastAccess( server.grp, time( NULL ) );
-
-    /*
-     * All the info we require is now in RAM, and we may generate
-     * lots of output (consider XOVER 2-3999), so release the lock
-     * while responding.
-     */
-    closeServer();
-    
     parseRange( arg, &first, &last, &n );
     if ( n == 0 )
 	first = last = server.artPtr;
@@ -1370,6 +1304,7 @@
 		      Ov_date( ov ), Ov_msgId( ov ), Ov_ref( ov ),
 		      Ov_bytes( ov ), Ov_lines( ov ) );
     putEndOfTxt();
+    Grp_setLastAccess( server.grp, time( NULL ) );
     return TRUE;
 }
 
@@ -1384,8 +1319,6 @@
     va_end( ap );
     Log_err( s );
     putStat( STAT_PROGRAM_FAULT, "%s", s );
-    fflush( stdout );
-    Log_dbg( "[S FLUSH]" );
 }
 
 /* Parse line, execute command and return FALSE, if it was the quit command. */
@@ -1406,24 +1339,20 @@
             if ( strcmp( c->name, s ) == 0 )
             {
                 ret = c->cmdProc( Utl_stripWhiteSpace( arg ), c );
-                fflush( stdout );
-                Log_dbg( "[S FLUSH]" );
                 return ret;
             }
     }
     putStat( STAT_NO_SUCH_CMD, "Command not recognized" );
-    fflush( stdout );
-    Log_dbg( "[S FLUSH]" );
     return TRUE;
 }
 
 static void
 putWelcome( void )
 {
+    initOutput();
     putStat( STAT_READY_POST_ALLOW, "NNTP server NOFFLE %s",
              Cfg_version() );
-    fflush( stdout );
-    Log_dbg( "[S FLUSH]" );
+    sendOutput();
 }
 
 static Bool
@@ -1449,54 +1378,37 @@
 Server_run( void )
 {
     Bool done;
-    int r;
     Str line;
 
     putWelcome();
     done = FALSE;
     while ( ! done )
     {
-	/*
-	 * If we've had the lock for more than 2 seconds,
-	 * force it to be released. Otherwise, if we have
-	 * the lock but have had it for < 2 secs, 
-	 * wait for a command line for a maximum
-	 * of 2 seconds. This is all an attempt at striking a
-	 * balance between efficient processing of commands
-	 * and hogging the lock.
-	 */
-	if ( server.running )
+	if ( Prt_getLn( line, stdin, -1 ) )
 	{
-	    time_t now;
+	    initOutput();
 
-	    now = time( NULL );
-	    if ( difftime( now, server.lastServerOpen ) > 2.0 )
+	    if ( ! initServer() )
+	    {
+		putFatal( "Cannot init server" );
+		done = TRUE;
+	    }
+	    else
+	    {
+		if ( ! parseAndExecute( line ) )
+		    done = TRUE;
+	    }
+
+	    if ( server.running )
 		closeServer();
-	}
-        r = waitCmdLn( line, ( server.running ) ? 2 : 0 );
-        if ( r < 0 )
+
+	    sendOutput();
+        }
+	else
         {
             Log_inf( "Client disconnected. Terminating." );
             done = TRUE;
         }
-        else if ( r == 0 )
-	{
-	    if ( server.running )
-		closeServer();
-	}
-	else /* ( r > 0 ) */
-	{
-	    if ( ! server.running )
-	    {
-                if ( ! initServer() )
-                {
-                    putFatal( "Cannot init server" );
-                    done = TRUE;
-                }
-            }
-            if ( ! parseAndExecute( line ) )
-                done = TRUE;
-        }
     }
     if ( server.running )
         closeServer();