root/trunk/bevutils/ServiceImplementation.d

Revision 20, 4.5 kB (checked in by teales, 1 year ago)

Bevutils files initial check-in.

Line 
1 /**
2  * Authors: Steve Teale - steve.teale@britseyeview.com
3  *
4  * Date: 2007/05/19
5  * History: V0.1
6  * License: Use freely for any purpose.
7  */
8 module bevutils.serviceimplementation;
9
10 import std.stdio;
11 import std.string;
12 import std.c.windows.windows;
13 import std.thread;
14 import bevutils.servicebase;
15 import bevutils.eventlogger;
16 import bevutils.log4d;
17 import bevutils.propertyfile;
18
19 extern (Windows)
20 {
21    BOOL Beep(DWORD dwFreq, DWORD dwDuration);
22 }
23
24 interface WorkerThread
25 {
26    int threadProc();
27    void setLog(Log4D log);
28    char[] threadName();
29    void setHost(ServiceImplementation si);
30    void setProperties(PropertyFile pf);
31    void setEventLogger(EventLogger el);
32 }
33 /**
34  * A class derived fromn ServiceBase to provide a more comprehensive implementation
35  * of a service, including:
36  *
37  * - Logging to file with rollover and limitation of file accumulation.<br>
38  * - Reading of an XML properties file on service start.<br>
39  * - Utilization of a number of threads for the actual implementation.
40  */
41 class ServiceImplementation : ServiceBase
42 {
43 protected:
44    PropertyFile _props;
45    char[] _abbrev;
46    Log4D _log;
47    bool _logging;
48    Thread[] _threads;
49    bool _stopFlag;
50     int _loglevel;
51
52    /**
53     * Single constructor to provide the service name to the base class, and note
54     * the abbreviation for use as log file prefix.
55     */
56    this(char[] serviceName, char[] abbrev)
57    {
58       super(serviceName);
59       _abbrev = abbrev;
60    }
61
62    void getAppProperties()
63    {
64       char[512] szPath;
65       int n = GetModuleFileNameA(null, szPath.ptr, 512);
66       if (!n)
67       {
68          throw new Exception("Unable to get executable path for properties.");
69       }
70       char[] s = szPath[0 .. n];
71       _props = new PropertyFile(s ~ ".config");
72    }
73
74    public void onServiceStart(char[][] args)
75    {
76       // Get the properties from the application properties file.  This is presumed to be called
77       // appname.exe.config, and to be in the same directory as the executable.
78       getAppProperties();
79
80       // Now create the service's log file if logging is specified by the existence of a logpath
81       // property.
82       _logging = false;
83       if (_props("logpath"))
84       {
85          char[] logpath = _props.getString("logpath");
86          int numlogs = _props.getInt("numlogs");
87          int maxlogsize = _props.getInt("maxlogsize");
88          _log = new Log4D(logpath, _abbrev, Log4D.Log4DStyle.STD, numlogs, maxlogsize);
89          _logging = true;
90          _log.logMessage("INFO", "Logging to " ~ logpath);
91       }
92         _loglevel = 0;
93         if (_props("verbosity"))
94            _loglevel = _props.getInt("loglevel");
95       int threads = 1;
96       if (_props("threads"))
97       {
98          threads = _props.getInt("threads");
99       }
100       _threads.length = threads;
101       int delegate() dg;
102       for (int i = 0; i < threads; i++)
103       {
104          WorkerThread wt = getThreadImpl(i);
105          if (_logging)
106             wt.setLog(_log);
107          wt.setHost(this);
108          wt.setProperties(_props);
109          wt.setEventLogger(_elog);
110          dg = &wt.threadProc;
111          _threads[i] = new Thread(dg);
112          _threads[i].start();
113          if (_logging)
114             _log.logMessage("INFO", wt.threadName() ~ " started as thread " ~ std.string.toString(i));
115       }
116    }
117
118    void onServiceStop()
119    {
120       _stopFlag = true;
121       for (;;)
122       {
123          int n = 0;
124          for (int i = 0; i <_threads.length; i++)
125          {
126             if (_threads[i].getState() != Thread.TS.TERMINATED)
127                n++;
128          }
129          if (!n)
130             break;
131          ReportStatusToSCMgr(SERVICE_STATES.SERVICE_STOP_PENDING, 0, 0);
132          Sleep(500);
133       }
134    }
135 public:
136
137    /**
138     * Override this method to create an instance of an object implementing WorkerThread
139     * FOR THREADS 0 - n-1.
140     */
141    abstract WorkerThread getThreadImpl(int n)
142    {
143       return null;
144    }
145
146    /**
147     * Your WorkerThread implementation must check this flag to determine when the thread should terminate.
148     */
149    bool StopFlag() { return _stopFlag; }
150
151    void logAlways(char[] category, char[] msg)
152    {
153     _log.logMessage(category, msg);
154    }
155
156     void logError(char[] msg)
157     {
158        _log.logMessage("ERROR", msg);
159     }
160
161     void logWarning(char[] msg)
162     {
163        if (_loglevel >= 1)
164            _log.logMessage("WARNING", msg);
165     }
166
167     void logInfo(char[] msg)
168     {
169        if (_loglevel >= 2)
170            _log.logMessage("INFO", msg);
171     }
172 }
Note: See TracBrowser for help on using the browser.