logserver.c

Go to the documentation of this file.
00001 /*!
00002  * \file        log/server/src/logserver.c
00003  * \brief       Log-Server main
00004  *
00005  * \date        03/02/2001
00006  * \author      Jork Loeser <jork.loeser@inf.tu-dresden.de>
00007  *
00008  * Buffering issues: We allow buffering of output to speed up logging.
00009  *
00010  * Currently, we do not deal with dynamic memory allocation, we use a
00011  * static array, allocated at compile-time. What would be the use of
00012  * dynamic allocation? As of today (03/01/2001), malloc() uses a
00013  * pre-allocated memory area, allocated from simple-dm prior to the
00014  * start of main(). So, this memory would be allocated anyway. Thus we
00015  * save the effort and use the static array.
00016  */
00017 /* (c) 2003 Technische Universitaet Dresden
00018  * This file is part of DROPS, which is distributed under the terms of the
00019  * GNU General Public License 2. Please see the COPYING file for details.
00020  */
00021 
00022 #include <assert.h>
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <stdlib.h>
00026 #include <l4/sys/types.h>
00027 #include <l4/sys/ipc.h>
00028 #include <l4/sys/kdebug.h>
00029 #include <l4/sys/syscalls.h>
00030 #include <l4/rmgr/librmgr.h>
00031 #include <l4/names/libnames.h>
00032 #include <l4/log/l4log.h>
00033 #include <l4/util/parse_cmd.h>
00034 #include <l4/util/l4_macros.h>
00035 
00036 #include "../include/log_comm.h"
00037 #include "stuff.h"
00038 #include "flusher.h"
00039 #include "tcpip.h"
00040 #include "config.h"
00041 #include "muxed.h"
00042 #include "log-server.h"
00043 
00044 int     verbose=0;
00045 unsigned buffer_size, buffer_head, buffer_tail;
00046 #if CONFIG_USE_TCPIP
00047 unsigned buffer_size = 4096;    /* we use a buffer size of 4KB per default
00048                                    when logging to the net. */
00049 #endif
00050 
00051 //! A string-buffer containing the received string
00052 static char message_buffer[LOG_BUFFERSIZE+5];
00053 
00054 //! Our own logstring
00055 char LOG_tag[9]="log";
00056 
00057 int     flush_local=1;
00058 int     flush_serial;
00059 int     serial_esc;
00060 
00061 #if CONFIG_USE_TCPIP
00062 bin_conn_t bin_conns[MAX_BIN_CONNS];
00063 int     flush_to_net=0;         // should we actually flush to the net?
00064 int     flush_muxed=1;          /* should we use multiplexed mode on
00065                                    net-output? */
00066 #endif
00067 
00068 int prio = 0x20;
00069 
00070 char buffer_array[OUTPUT_BUFFER_SIZE];
00071 
00072 #define min(a,b) ((a)<(b)?(a):(b))
00073 
00074 /* management for buffered output */
00075 static void init_buffer(void){
00076   if(buffer_size && buffer_size < 10) buffer_size = 10;
00077 
00078   if(buffer_size > sizeof(buffer_array)){
00079     LOGd(CONFIG_LOG_NOTICE,
00080             "requested buffersize of %d, shrinking to %zd\n",
00081             buffer_size, sizeof(buffer_array));
00082     buffer_size = sizeof(buffer_array);
00083   }
00084   buffer_head = buffer_tail = 0;
00085   buffer_array[buffer_head] = 0;
00086 #if CONFIG_USE_TCPIP
00087   memset(bin_conns, 0, sizeof(bin_conns));
00088 #endif
00089 }
00090 
00091 /* If buffering is enabled, try to print a string into the internal buffer.
00092    If it doesnt fit, flush the buffer and try again. */
00093 static void print_buffered(const char*data){
00094   int   len;
00095   int   cur_len;
00096   int   tail;
00097   int   free;
00098 
00099   len = strlen(data);
00100   if(buffer_size){
00101       while(len>0){
00102           tail = buffer_tail;
00103           if(tail>buffer_head) free = tail-buffer_head-1;
00104           else free = buffer_size-buffer_head+tail - 1;
00105 
00106           assert(free>=0);
00107           LOGd(CONFIG_LOG_RINGBUFFER,
00108                   "head=%d, tail=%d, size=%d, free=%d, len=%d\n",
00109                   buffer_head, buffer_tail, buffer_size, free, len);
00110 
00111           if(free==0){
00112               flush_buffer();
00113               continue;
00114           }
00115 
00116           if(tail>buffer_head){  // free area is between head and tail
00117               cur_len = min(free,len);
00118               assert(cur_len>0);
00119               LOGd(CONFIG_LOG_RINGBUFFER,
00120                       "filling %d+%d\n", buffer_head, cur_len);
00121               memcpy(buffer_array+buffer_head, data, cur_len);
00122           } else {
00123               /* head >= tail, free area wraps arround. We only write the
00124                  topmost bytes and cycle again. We can write at least 1 byte,
00125                  to the topmost bytes, but we must leave one byte between
00126                  head and tail! If tail==0, this byte must be the last byte,
00127                  otherwise somewhere in the beginning of the buffer.
00128               */
00129               cur_len = buffer_size-buffer_head-(tail==0);
00130               cur_len = min(cur_len,len);
00131               assert(cur_len>0);
00132               LOGd(CONFIG_LOG_RINGBUFFER,
00133                       "filling %d+%d\n", buffer_head, cur_len);
00134               memcpy(buffer_array+buffer_head, data, cur_len);
00135           }
00136           len-=cur_len;
00137           data+=cur_len;
00138           if(buffer_head+cur_len == buffer_size) buffer_head = 0;
00139           else buffer_head+=cur_len;
00140           assert(buffer_head<buffer_size);
00141       }
00142   } else {
00143       if(flush_local){
00144           outstring(data);
00145       }
00146 #if CONFIG_USE_SERIAL
00147       if(flush_serial) serial_flush(data, strlen(data));
00148 #endif
00149   }
00150 }
00151 
00152 static void parse_args(int argc, const char**argv){
00153     parse_cmdline(&argc, &argv,
00154                   'v', "verbose", "verbose mode",
00155                   PARSE_CMD_SWITCH, 1, &verbose,
00156 #if CONFIG_USE_TCPIP
00157                   ' ', "net", "use TCP/IP network connections",
00158                   PARSE_CMD_SWITCH, 1, &flush_to_net,
00159                   ' ', "nonet", "do not use TCP/IP network connections",
00160                   PARSE_CMD_SWITCH, 0, &flush_to_net,
00161                   'm', "muxed", "flush in muxed mode to TCP/IP",
00162                   PARSE_CMD_SWITCH, 1, &flush_muxed,
00163                   'M', "nomuxed", "do not flush in muxed mode",
00164                   PARSE_CMD_SWITCH, 0, &flush_muxed,
00165                   ' ', "ip", "IP address to use",
00166                   PARSE_CMD_STRING, "", &ip_addr,
00167 #endif
00168                   'l', "local", "flush to local console",
00169                   PARSE_CMD_SWITCH, 1, &flush_local,
00170                   'L' ,"nolocal", "do not flush to local console",
00171                   PARSE_CMD_SWITCH, 0, &flush_local,
00172 #if CONFIG_USE_SERIAL
00173                   's' ,"comport", "flush to specified serial interface",
00174                   PARSE_CMD_INT, 0, &flush_serial,
00175                   'e', "serial-esc", "enter kdebug on esc on serial",
00176                   PARSE_CMD_SWITCH, 1, &serial_esc,
00177 #endif
00178                   'b', "buffer", "buffered mode",
00179                   PARSE_CMD_INT, 0, &buffer_size,
00180                   ' ', "flushprio", "priority of flusher thread",
00181                   PARSE_CMD_INT, 0x20, &flusher_prio,
00182                   'p', "prio", "priority of main thread",
00183                   PARSE_CMD_INT, 0x20, &prio,
00184                   0);
00185 
00186 }
00187 
00188 void
00189 log_outstring_component (CORBA_Object _dice_corba_obj,
00190     int flush_flag,
00191     const char* str,
00192     CORBA_Server_Environment *_dice_corba_env)
00193 {
00194     if (verbose && str && str[0])
00195     {
00196       char buf[10];
00197       sprintf(buf, l4util_idfmt_adjust":", l4util_idstr(*_dice_corba_obj));
00198       print_buffered(buf);
00199     }
00200     print_buffered(str);
00201     if(flush_flag ||
00202         strstr(message_buffer, "***"))
00203         flush_buffer();
00204 }
00205 
00206 int
00207 log_channel_open_component (CORBA_Object _dice_corba_obj,
00208     l4_snd_fpage_t page,
00209     int channel,
00210     CORBA_Server_Environment *_dice_corba_env)
00211 {
00212 #if CONFIG_USE_TCPIP
00213     int ret = channel_open(page.fpage, channel);
00214     _dice_corba_env->rcv_fpage = channel_get_next_fpage();
00215     return ret;
00216 #else
00217     return -1;
00218 #endif
00219 }
00220 
00221 int
00222 log_channel_write_component (CORBA_Object _dice_corba_obj,
00223     int channel, 
00224     unsigned int offset,
00225     unsigned int size,
00226     CORBA_Server_Environment *_dice_corba_env)
00227 {
00228 #if CONFIG_USE_TCPIP
00229     return channel_write(channel, offset, size);
00230 #else
00231     return -1;
00232 #endif
00233 }
00234 
00235 int
00236 log_channel_flush_component (CORBA_Object _dice_corba_obj,
00237     int channel,
00238     CORBA_Server_Environment *_dice_corba_env)
00239 {
00240 #if CONFIG_USE_TCPIP
00241     return channel_flush(channel);
00242 #else
00243     return -1;
00244 #endif
00245 }
00246 
00247 int
00248 log_channel_close_component (CORBA_Object _dice_corba_obj,
00249     int channel,
00250     CORBA_Server_Environment *_dice_corba_env)
00251 {
00252 #if CONFIG_USE_TCPIP
00253     return channel_close(channel);
00254 #else
00255     return -1;
00256 #endif
00257 }
00258 
00259 static void*
00260 msg_alloc(unsigned long size)
00261 {
00262     if (size != LOG_BUFFERSIZE)
00263         return 0;
00264     return message_buffer;
00265 }
00266 
00267 int main(int argc, const char**argv){
00268   int err;
00269   CORBA_Server_Environment env = dice_default_server_environment;
00270 
00271   parse_args(argc,argv);
00272 
00273   init_buffer();
00274   
00275   rmgr_init();
00276   err = rmgr_set_prio(l4_myself(), prio);
00277   if(err){
00278       LOG_Error("rmgr_set_prio(%d): %d", prio, err);
00279       return 1;
00280   }
00281 
00282   err = flusher_init();
00283   if(err){
00284       LOG_Error("Serious problems initalizing the flusher.\n");
00285   }
00286 
00287   if(names_register(LOG_NAMESERVER_NAME)==0){
00288     LOG_Error("Cannot register at nameserver, falling asleep\n");
00289     return 1;
00290   }
00291   if(verbose){
00292       printf("Server started and registered as \"%s\"\n",
00293               LOG_NAMESERVER_NAME);
00294 #if CONFIG_USE_TCPIP
00295     printf("Logging to: %s%s%s\n",
00296            flush_local?"console ":"",
00297            flush_to_net?"network ":"",
00298            flush_serial?"serial ":""
00299         );
00300 #else
00301     printf("Logging to: %s%s\n",
00302            flush_local?"kdebug ":"",
00303            flush_serial?"serial":"");
00304 #endif
00305     printf("Buffersize: %d\n", buffer_size);
00306   }
00307 
00308 #if CONFIG_USE_TCPIP
00309   env.rcv_fpage = channel_get_next_fpage();
00310 #else
00311   env.rcv_fpage.fpage = 0;
00312 #endif
00313   env.malloc = msg_alloc;
00314 
00315   strcpy(message_buffer+LOG_BUFFERSIZE,"...\n");
00316   log_server_loop (&env);
00317 }

Generated on Wed Apr 11 06:40:52 2012 for Logging and output facility for DROPS by  doxygen 1.5.6