From f656ec8b1557b3e413d7b69deac636e63c7a4f6b Mon Sep 17 00:00:00 2001 From: sc Date: Sat, 30 Dec 2000 22:33:05 +0000 Subject: Updated for use with multiplexers Moved a part to TextService.cc --- comm/OLD/TextStream.cc | 422 +------------------------------------------------ 1 file changed, 3 insertions(+), 419 deletions(-) diff --git a/comm/OLD/TextStream.cc b/comm/OLD/TextStream.cc index 790a03e..7f1764f 100644 --- a/comm/OLD/TextStream.cc +++ b/comm/OLD/TextStream.cc @@ -13,8 +13,6 @@ */ #include "TextStream.h" -#include "TimeOut.h" -#include "PortServer.h" #include "Multiplexer.h" #include "error.h" #include @@ -33,8 +31,8 @@ extern "C" { /*? Construct a \typ{UchTextStream}. ?*/ -UchTextStream :: UchTextStream () -: UchBufStream () +UchTextStream :: UchTextStream (UchAddress* bindTo, UchAddress* connectTo) +: UchBufStream (bindTo, connectTo) { } @@ -230,7 +228,7 @@ should call the default implementation. void UchTextStream :: Close () { - Mpx->Remove (*this); + Remove (); } /*? @@ -742,417 +740,3 @@ UchTextLine :: Index (int value) const return i; return -1; } - -//---------------- constants - -// we start with a few quick retries -// AbandonRetries doubles the time and decrement the retries until 1 -// 2 secs * 5 = 10 secs -// 4 secs * 4 = 16 secs -// 8 secs * 3 = 24 secs -// 16 secs * 2 = 32 secs -// 32 secs * 1 = 32 secs -// total = 15 retries in 114 secs ~ 2 minutes -// we want this to be significantly longer than the REG_TIME of the port server - -#define RETRY_TIME 2 -#define MAX_RETRIES 5 - -//---------------- ServiceStarter - -class UchServiceStarter : public UchBaseTimeOut { -friend class UchTextService; - -protected: - UchTextService* Service; - int Retries; - int Max; - -public: - UchServiceStarter (UchTextService*, int, int); - void Handle (Millisecond); -}; - -UchServiceStarter :: UchServiceStarter (UchTextService* s, int retry, int maxr) -: UchBaseTimeOut (*s->GetMultiplexer (), retry * 1000), - Service (s), - Retries (0), - Max (maxr) -{ -} - -void -UchServiceStarter :: Handle (Millisecond) -{ - /* UchServiceStarters are not timers triggered on signals. - For that reason, Handle is allowed to be complex. */ - - if (! Service) - return; - - fprintf (stderr, "ServiceStarter::TimeOut, attempting restart\n"); - if (Service->GetStatus () == UchTextService::isRunning - || Service->Restart () == UchTextService::isRunning) { - Stop (); - Service->Starter = 0; - delete this; - return; - } - - if (++Retries >= Max) { - Stop (); - if (Max <= 1) { - fprintf (stderr, "ServiceStarter::TimeOut, abandoning restart\n"); - Service->Starter = 0; - Service->AbandonRestart (); - delete this; - } else { - Max--; - Retries = 0; - ChangePeriod (GetPeriod () * 2); - Restart (); - } - } -} - - -/*? -Construct an empty \var{UchTextService}. -When using this constructor, the application must call \fun{Init} at a later -time in order to define the server to connect to. -The initial state of the service is \var{isLost}, since the actual -connection to the server is not established yet. -?*/ -UchTextService :: UchTextService () -: UchTextStream (), - StatusFlag (isLost), - Starter (0), - Closed (false), - User (), - Service (), - Host () -{ -} - -/*? -Construct a \var{UchTextService} connected to server \var{s} on host \var{h}. -This is equivalent to the empty constructor followed by a call to \fun{Init}. -?*/ -UchTextService :: UchTextService (UchBaseMultiplexer& mpx, const char* s, const char* h) -: UchTextStream (), - StatusFlag (isLost), - Starter (0), - Closed (false), - User (), - Service (), - Host () -{ - Init (mpx, s, h); -} - -/*? -The (protected) destructor. -Call \fun{Close} or \fun{CloseNow} to close down the connection and -delete the service. -?*/ -UchTextService :: ~UchTextService () -{ - if (Starter) - delete Starter; -} - -/*? -This protected virtual function is called by \fun{UchTextStream::HandleRead} -when an end-of-file is read or when a read failed. -It calls \var{LostServer} so that an attempt to reconnect to the server -can be made. -?*/ -void -UchTextService :: Closing (bool) -{ - fprintf (stderr, "UchTextService::Closing, lost server\n"); - StatusFlag = isLost; - LostServer (); -} - -/*? -Attempt to connect to the server. -If the address of the server cannot be retrieved from the port server, -this function sets the state of the service to \var{isUnavailable} -and returns. -If an address is obtained from the port server, this function tries to connect -to that address. -If this fails, it sets the state to \var{isError} and returns. -Otherwise, it sets the state to \var{isRunning} and calls the virtual -function \fun{GotServer}. -The service is automatically registered with the multiplexer, with mode \var{IONone} -the first time the connection is established. -?*/ -UchTextService::status -UchTextService :: Restart () -{ - UchInetAddress* addr = PortServerInquire ("portserv", Service, Host); - if (! addr) { -#if 0 - // *** horrible patch - see portcli.C. This info should be returned by PortServerInquire - extern bool PortServerInquireSysError; - if (PortServerInquireSysError) { - Log ("TSERVICE::Restart", "no agent manager"); - return StatusFlag = isError; - } -#endif - fprintf (stderr, "UchTextService::Restart, no address in port server\n"); - return StatusFlag = isUnavailable; - } - if (addr->Host () == 0 && addr->Port () == 0) { -// Log ("TSERVICE::Restart", "agent being launched by agent manager"); - return StatusFlag = isLost; - } - - ConnectTo (addr); - - bool wasopened = Fd.Opened (); - bool setup = true; - if (wasopened) { - // we are in trouble because a stream socket can be connected - // only once and a channel is immutable... - // so we have to fake a reopen - int ofd = FilDes (); - if (ofd >= 0) { - close (ofd); - int nfd = socket (ConnectedTo () ->Family (), SockType (), 0); -// fprintf (stderr, "UchTextService::Restart, reopening socket: %d -> %d\n", (void*) ofd, (void*) nfd); - if (nfd < 0) { - setup = false; - } else if (nfd != ofd) { - dup2 (nfd, ofd); - close (nfd); - } - } - } - if (setup) - setup = Setup (); - if (! wasopened) { - SetMode (IONone); - if (Mpx) - Mpx->Add (this); ///////// Mpx was initialized by Init - } - if (! setup) { - fprintf (stderr, "UchTextService::Restart, could not setup connection\n"); - return StatusFlag = isError; - } - - StatusFlag = isRunning; - if (Starter) // do not log if got server at first attempt - fprintf (stderr, "UchTextService::Restart, got server\n"); - GotServer (); - return StatusFlag; -} - -/*? -This protected function arranges for a connection to be attempted in -\var{retry_time} seconds. -If the connection cannot be established after \var{maxr} retries, -\var{retry_time} is doubled and \var{maxr} is decremented and new attempts -are made with these new values. -When the number of retries is null, then the virtual function -\fun{AbandonRestart} is called and no further attempts are made. -If \var{retry_time} is 0, any pending attempts are cancelled. -If \var{retry_time} or var{maxr} is negative, suitable default values are used. -?*/ -void -UchTextService :: AutoStart (int retry_time, int maxr) -{ - if (retry_time < 0) - retry_time = RETRY_TIME; - if (maxr < 0) - maxr = MAX_RETRIES; - - if (retry_time == 0) { // cancel auto-start - if (Starter) { - delete Starter; - Starter = 0; - } - return; - } - if (Starter) { - Starter->ChangePeriod (retry_time); - Starter->Retries = 0; - Starter->Max = maxr; - } else if (Mpx) { - Starter = new UchServiceStarter (this, retry_time, maxr); - } else - fprintf (stderr, "UchTextService::AutoStart, no multiplexer for time-out\n"); -} - -/*? -This protected virtual function is called when the connection to the server -has been broken. -By default, it resets the mode of the channel to \var{IONone} so that the -multiplexer does not attempt to read from the server. -Derived classes can redefine this function, but the redefinition should -call the default implementation. -?*/ -void -UchTextService :: LostServer () -{ - Mpx->SetMode (*this, IONone); - AutoStart (); -} - -/*? -This protected virtual function is called when the connection to the server -has been established. -By default, it sets the mode of the channel to \var{IORead} so that the -multiplexer can monitor the channel. -If the output buffer is not empty, it sends it to the server by calling -\fun{DoSend}. -Derived classes can redefine this function, but the redefinition should -call the default implementation. -?*/ -void -UchTextService :: GotServer () -{ - Mpx->SetMode (*this, IORead); - if (OutBuffer.BufLength () != 0) - Flush (); -} - -/*? -This protected virtual function is called when the connection cannot -be restarted (see \fun{AutoStart}). -By default it calls \fun{CloseNow} which should ultimately destroy the object. -A derived class can redefine this function to take whatever clean-up action -is required. -?*/ -void -UchTextService :: AbandonRestart () -{ - CloseNow (); -} - -/*? -This implementation of the protected virtual function \fun{UchTextStream::Execute} -always return \var{isCmdOk}. -This is suitable for the global function \var{TellServer}. -Derived classes generally do redefine this function. -?*/ -UchTextStream::cmd_res -UchTextService :: Execute (const UchTextLine&) -{ - // just discard received request by default - // (suitable for TellServer below) - return isCmdOk; -} - -/*? -This implementation of the protected virtual function \fun{UchBufStream::Flush} -writes the output buffer only if the state of the connection is -\var{isRunning}. -Otherwise, the outgoing requests accumulate in the ouput buffer until the -connection is established. -This function also closes down the connection by calling \var{MpxRemoveChannel} -if \fun{Close} has been called before the connection ws actually established. -?*/ -void -UchTextService :: Flush () -{ - if (StatusFlag == isRunning) { - Write (OutBuffer); - if (Closed) - Mpx->Remove (*this); - } -} - -/*? -Define the server and host to connect to. This function must be used -if the object was constructed with the default constructor. -If the connection to the server cannot be established, \fun{Init} calls -\var{AutoStart} to attempt the connection later. -?*/ -void -UchTextService :: Init (UchBaseMultiplexer& mpx, const char* s, const char* h) -{ - if (StatusFlag == isRunning) - return; - - Service = s; - Host = h; - Mpx = &mpx; - - StatusFlag = Restart (); - if (StatusFlag == isError) { - // try to run the agent manager - if (fork () != 0) { - // we are the parent process, and we become the agent manager - // *** how to have the agent manager survive the client ??? - ::Error (ErrLog, "TSERVICE::Init", "trying to run agentman"); - if (execlp ("agentman", "agentman", 0) != 0) - ::Error (ErrWarn, "TSERVICE::Init", "could not run agentman"); - } - } - // delay retry - if (StatusFlag != isRunning) - AutoStart (); -} - -/*? -Return the current retry time for the auto-restart of the connection. -If the connection is not in auto-restart mode, return -1; -?*/ -int -UchTextService :: GetRetryTime () -{ - return Starter ? Starter->GetPeriod () / 1000 : -1; -} - -/*? -Return the current maximum number of retries for the auto-restart of the connection. -If the connection is not in auto-restart mode, return -1; -?*/ -int -UchTextService :: GetMaxRetries () -{ - return Starter ? Starter->Max : -1; -} - -/*? -Remove this service from the multiplexer if the connection is established -or if the output buffer is empty. -Otherwise, mark the connection as being closed; -in this case, the output buffer will be sent when the connection is etablished, -and then the connection will be closed. -?*/ -void -UchTextService :: Close () -{ - Closed = true; - if (StatusFlag == isRunning || OutBuffer.BufLength () == 0) - Mpx->Remove (*this); -} - -/*? -Remove this service from the multiplexer, whatever -the state of the connection is. -?*/ -void -UchTextService :: CloseNow () -{ - Mpx->Remove (*this); -} - -#if 0 -/*? -This global function provides the simplest interface to send a request \var{req} -to a server \var{sname} on host \var{host}. -?*/ -bool -TellServer (const char* sname, const char* host, const char* req) -{ - UchTextService* serv = new UchTextService; - serv->Init (sname, host); - serv->Send (req); - serv->Close (); - return true; -} -#endif -- cgit v1.1