Changeset 262 for Evidence/Doc


Ignore:
Timestamp:
07/26/10 17:53:31 (14 years ago)
Author:
ogrimm
Message:
Removed signaling to invoke ConfigChanged(), now it is run as separate thread. New command '/ResetMessage'
File:
1 edited

Legend:

Unmodified
Added
Removed
  • Evidence/Doc/Evidence.tex

    r255 r262  
    130130\item Provides a method for configuration requests. If the configuration data is not available, the application terminates with a  message of FATAL severity unless default data is given.
    131131\item Provides a method for safely translating DIM service data into text.
    132 \item Implements the virtual DIM methods \lstinline{exitHandler()}. It can be called through a standard DIM command \lstinline{SvrName/EXIT}, taking a single integer as argument. Upon first invocation, the handler just sets the flag \lstinline{ExitRequest} which should be handled by the application. Upon second invocation, it will call \lstinline{exit()}. A special functionality is given to the argument value 0: it instructs the server to reset its message severity to INFO, without exiting. This is used by the \lstinline{Alarm} server if it receives a command to reset an alarm level, but is also available to the user. The user application can override this handler.
     132\item Implements the virtual DIM methods \lstinline{exitHandler()}. It can be called through a standard DIM command \lstinline{SvrName/EXIT}, taking a single integer as argument. Upon first invocation, the handler just sets the flag \lstinline{ExitRequest} which should be handled by the application. Upon second invocation, it will call \lstinline{exit()}. The user application can override this handler.
     133\item Provides a DIM command \lstinline{SvrName/ResetMessage}. It will set the message service to INFO severity with the information which client issued the command. This can be used to remove a WARN, ERROR or FATAL serverity once the problem has been fixed. The \lstinline{Alarm} server uses this command if it is instructed to reset an alarm level. The command takes no arguments.
    133134\item Implements the virtual DIM methods \lstinline{errorHandler()}. The error handler will issue a message with ERROR severity that contains the DIM error code. The user application can override this handler.
    134135\item Installs signal handler for SIGQUIT (ctrl-backspace), SIGTERM, SIGINT (ctrl-c), and SIGHUP (terminal closed). The signal handler sets first \lstinline{ExitRequest}, and on second invocation calls \lstinline{exit()}. After instantiating the class, the programmer may override the handlers.
     
    157158    void SendToLog(const char *, ...);
    158159    string GetConfig(string, string = string());
    159     void ActivateSignal(int);
     160        virtual void ConfigChanged() {};
    160161    void Lock();
    161162    void Unlock();
     
    163164    static bool ServiceOK(DimInfo *);
    164165    static bool ServiceOK(DimRpcInfo *);
     166        static bool ServiceOK(DimCurrentInfo *);
    165167    static vector<string> Tokenize(const string &, const string & = " ");
    166168
     
    179181\underline{\lstinline{GetConfig()}} issues, on first invocation, a DIM remote procedure call to the configuration server to retrieve the required data and returns it as a string. The second argument gives the data to be returned in case the server is unavailable or cannot provide the requested data. If in this case the second string is empty, the program terminates with a FATAL message. Using the service \lstinline{Config/ModifyTime}, the server keeps track of changes to the configuration file in the background. Upon subsequent requests for the same configuration data, it only issues a remote procedure call again if the file changed in the meantime. If not, the same data already retrieved is returned. This way, this function can be repeatedly called, even at high rate, without generating unnecessary load to the configuration server (as the configuration file does not change frequently).
    180182
    181 \underline{\lstinline{ActivateSignal()}} is used to define a signal that should be emitted to the main thread in case the configuration file changes. See Sect.\,\ref{ConfigHandling} for details. No signal will be emitted if not set by this routine.
    182 
    183 The methods \underline{\lstinline{Lock()}} and \underline{\lstinline{Unlock()}} work on an internal mutex.\footnote{Its type is \lstinline{PTHREAD_MUTEX_ERRORCHECK}. In case an already locked mutex is re-locked, the corresponding system call will therefore return a error and thus avoid dead-locking. Error messages from \lstinline{Lock()} and \lstinline{Unlock()} are written to the console and to the log file. They are not published using \lstinline{Message()} since this method itself uses locking and calling it would result in an infinite recursion.} They are used by \lstinline{GetConfig()} but are also available for the user application to serialize access from multiple threads. If a signal is set by \lstinline{ActivateSignal()}, it is masked before locking and unmasked after unlocking. Calling functions in the locked state should be avoided as it might result in re-locking.
     183The virtual method \underline{\lstinline{ConfigChanged()}} is executed in a separate thread when the configuration file changes. It can be reimplemented by the application. Calls to \lstinline{GetConfig()} from this method will be blocking and thus result in updated configuration data.
     184
     185The methods \underline{\lstinline{Lock()}} and \underline{\lstinline{Unlock()}} work on an internal mutex.\footnote{Its type is \lstinline{PTHREAD_MUTEX_ERRORCHECK}. In case an already locked mutex is re-locked, the corresponding system call will therefore return a error and thus avoid dead-locking. Error messages from \lstinline{Lock()} and \lstinline{Unlock()} are written to the console and to the log file. They are not published using \lstinline{Message()} since this method itself uses locking and calling it would result in an infinite recursion.} They are used by \lstinline{GetConfig()} but are also available for the user application to serialize access from multiple threads. Calling functions in the locked state should be avoided as it might result in re-locking.
    184186
    185187The static method \underline{\lstinline{ToString()}} translates the contents of a DIM service safely into a string that is returned. As no consistency between a service format and the contained data is guaranteed by DIM, precautions are necessary to avoid buffer overruns. The method currently handles the standardized message format \lstinline{"I:1;C"}, arrays of numbers and strings. All other formats are translated into a hex representation. The arguments are the DIM service format, a pointer to the service data and the data size in bytes. It is thread safe as it uses only the arguments and dynamically allocated storage.
    186188
    187 The two variants of the static method \underline{\lstinline{ServiceOK()}} take a pointer to a received service update or result of a remote procedure call (as available in the respective handlers) and safely checks if its contents is identical to the constant \lstinline{NO_LINK}. If so, they return false. If using the same constant in the service declaration, this provides a safe way of being informed if a particular service becomes unavailable. Then, the handler is called once for that service with the data content \lstinline{NO_LINK}.
     189The static methods \underline{\lstinline{ServiceOK()}} take a pointer to a received service update or result of a remote procedure call (as available in the respective handlers) and safely checks if its contents is identical to the constant \lstinline{NO_LINK}. If so, they return false. If using the same constant in the service declaration, this provides a safe way of being informed if a particular service becomes unavailable. Then, the handler is called once for that service with the data content \lstinline{NO_LINK}.
    188190
    189191\underline{\lstinline{Tokenize()}} takes the string from the first argument, tokenizes it using the characters contained the second argument as delimeters, and returns a vector of strings containing all tokens.
     
    358360As a first step in achieving this, the application should not store the obtained configuration data internally, but always re-request it using the method \lstinline{GetConfig()} described in Sect.\,\ref{EvidenceServer-Methods}. This method will only issue a remote procedure call to the \lstinline{Config} server if the configuration file has been modified since the last invocation. So calling this method even at high rate will not load the configuration server at all if the configuraton file is unchanged, but will yield up-to-date information if it did change.
    359361
    360 The remote procedure call is blocking when called from the main thread, and non-blocking, using an \lstinline{rpcInfoHandler()}, when called from any other thread (especially also from the DIM handler thread). Blocking execution means that the remote procedure call will wait until the data has arrived from the server before returning to the application, whereas non-blocking execution will return immediately and invoke a handler later when the data arrived. This procedure is necessary since a blocking remote procedure call from \lstinline{infoHandler()} will result in a dead-lock.
     362The remote procedure call is blocking when called from the main thread or from the method \lstinline{ConfigChanged()} (which runs in a separate thread). It is non-blocking, using an \lstinline{rpcInfoHandler()}, when called from any other thread, especially also from the DIM handler thread. Blocking execution means that the remote procedure call will wait until the data has arrived from the server before returning to the application, whereas non-blocking execution will return immediately and invoke a handler later when the data arrived. This procedure is necessary since a blocking remote procedure call from \lstinline{infoHandler()} will result in a dead-lock.
    361363
    362364In the non-blocking case, the call to \lstinline{GetConfig()} returns still the previous, non-updated data even if the configuration file changed. The result of the non-blocking remote procedure call can only be processed by DIM once the current and all queued handler invocations have finished. When this is done, updated data will be returned by subsequent calls to \lstinline{GetConfig()}.
     
    364366\subsection{\lstinline{ConfigChanged()}}
    365367
    366 An alternative, albeit for the programmer more demanding, procedure for semi-automatic updates on configuration information is to implement the method \lstinline{ConfigChanged()} in the user class. This method can be invoked through a signaling mechanism by the \lstinline{EvidenceServer} class.
    367 
    368 To this end, first \lstinline{ActivateSignal()} has to be called with a signal number that should be used for announcing configuration changes (for example, \lstinline{SIGUSR1}). That signal is send to the main thread when the service \lstinline{Config/ModifyTime} changes. The signal is caught by the internal signal handler of the \lstinline{EvidenceServer} class which in turn calls the method \lstinline{ConfigChanged()}. It is declared as \lstinline{virtual} in the class and defined as an empty function. The user application can override this by declaring and defining the method itself. This method is then executed in the main thread and thus \lstinline{GetConfig()} will use blocking connections to get always up-to-date data.
    369 
    370 However, it must be kept in mind that this routine is running as part of the signal handler. The normal main thread execution was interrupted at an arbitrary point by the signal, thus suitable protection must be employed by the programmer when accessing common data structures. To ease that, the \lstinline{EvidenceServer} class contains the pair of methods \lstinline{Lock()} and \lstinline{Unlock()} that work on an class internal mutex. When the mutex is acquired, also the signal declared by \lstinline{ActivateSignal()} is disabled, thus preventing interruptions in case a configuration update occurs in the locked state. The mutex type is \lstinline{PTHREAD_MUTEX_ERRORCHECK} and therefore includes error checking: no dead-lock will occur if double locking, but the program will terminate with a \lstinline{FATAL} message.   
     368An alternative, albeit for the programmer more demanding, procedure for semi-automatic updates on configuration information is to reimplement the virtual method \lstinline{ConfigChanged()} in the user class. This method is invoked as a separate thread by the \lstinline{EvidenceServer} class whenever the service \lstinline{Config/ModifyTime} changes (and also at program start-up). As it is not running within the DIM handler thread, \lstinline{GetConfig()} will use blocking connections to get immediately up-to-date data when called from \lstinline{ConfigChanged()}.
     369
     370Running in a separate thread requires suitable protection by the programmer when accessing common data structures. To ease that, the \lstinline{EvidenceServer} class contains the pair of methods \lstinline{Lock()} and \lstinline{Unlock()} that work on an class internal mutex. The mutex type is \lstinline{PTHREAD_MUTEX_ERRORCHECK} and therefore includes error checking: no dead-lock will occur if double locking, but the program will terminate with a \lstinline{FATAL} message.   
    371371
    372372
Note: See TracChangeset for help on using the changeset viewer.