WvStreams
wvstreamsdaemon.cc
00001 /* -*- Mode: C++ -*-
00002  * Worldvisions Tunnel Vision Software:
00003  *   Copyright (C) 1997-2005 Net Integration Technologies, Inc.
00004  *
00005  * High-level abstraction for creating daemon processes that do
00006  * nothing but listen on a list of WvStreams and add connections
00007  * to the global list.
00008  */
00009 
00010 #include "wvstreamsdaemon.h"
00011 
00012 #ifndef _WIN32
00013 #include <signal.h>
00014 #endif
00015 
00016 void WvStreamsDaemon::init(WvDaemonCallback cb)
00017 {
00018     do_full_close = false;
00019     setcallback(cb);
00020 #ifndef _WIN32
00021     signal(SIGPIPE, SIG_IGN);
00022 #endif
00023 }
00024 
00025 void WvStreamsDaemon::do_start()
00026 {
00027     WvDaemon::do_start();
00028     
00029     callback();
00030 }
00031 
00032 void WvStreamsDaemon::do_run()
00033 {
00034     if (streams.isempty())
00035     {
00036         log(WvLog::Error, "No streams; exiting\n");
00037         die();
00038     }
00039 
00040     while (should_run())
00041     {
00042         WvDaemon::do_run();
00043         WvIStreamList::globallist.runonce();
00044     }
00045 }
00046 
00047 void WvStreamsDaemon::do_stop()
00048 {
00049     WvIStreamList::Iter stream(streams);
00050     for (stream.rewind(); stream.next(); )
00051         WvIStreamList::globallist.unlink(stream.ptr());
00052     streams.zap();
00053     if (do_full_close || want_to_die())
00054         WvIStreamList::globallist.zap();
00055     
00056     WvDaemon::do_stop();
00057 }
00058 
00059 void WvStreamsDaemon::add_stream(IWvStream *istream,
00060         bool autofree, const char *id)
00061 {
00062     streams.append(istream, false, id);
00063     // FIXME: we should pass in "id" here, but things are not happy in
00064     // const-correctness-land.
00065     WvIStreamList::globallist.append(istream, autofree, id);
00066 }
00067 
00068 void WvStreamsDaemon::add_restart_stream(IWvStream *istream, bool autofree,
00069                                          const char *id)
00070 {
00071     add_stream(istream, autofree, id);
00072     
00073     istream->setclosecallback(wv::bind(&WvStreamsDaemon::restart_close_cb,
00074                                        this, istream, id));
00075 }
00076 
00077 void WvStreamsDaemon::add_die_stream(IWvStream *istream,
00078         bool autofree, const char *id)
00079 {
00080     add_stream(istream, autofree, id);
00081     
00082     istream->setclosecallback(wv::bind(&WvStreamsDaemon::die_close_cb, this,
00083                                        istream, id));
00084 }
00085 
00086 void WvStreamsDaemon::restart_close_cb(IWvStream *s, const char *id)
00087 {
00088     if (should_run())
00089     {
00090         WvString err = s->geterr() ? s->errstr() : "no error";
00091         log(WvLog::Error, "%s is closed (%s); restarting\n",
00092                 id ? id : "Stream", err);
00093         restart();
00094     }
00095 }
00096 
00097 void WvStreamsDaemon::die_close_cb(IWvStream *s, const char *id)
00098 {
00099     if (should_run())
00100     {
00101         WvString err = s->geterr() ? s->errstr() : "no error";
00102         log(WvLog::Error, "%s is closed (%s); dying\n",
00103             id ? id : "Stream", err);
00104         die();
00105     }
00106 }
00107 
00108 void WvStreamsDaemon::setcallback(WvDaemonCallback cb)
00109 {
00110     callback = cb;
00111 }
00112