]> git.stg.codes - stg.git/blob - projects/stargazer/settings_impl.cpp
Split SETTINGS to interface and implementation
[stg.git] / projects / stargazer / settings_impl.cpp
1 /*
2  *    This program is free software; you can redistribute it and/or modify
3  *    it under the terms of the GNU General Public License as published by
4  *    the Free Software Foundation; either version 2 of the License, or
5  *    (at your option) any later version.
6  *
7  *    This program is distributed in the hope that it will be useful,
8  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *    GNU General Public License for more details.
11  *
12  *    You should have received a copy of the GNU General Public License
13  *    along with this program; if not, write to the Free Software
14  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  */
16
17 /*
18  *    Date: 27.10.2002
19  */
20
21 /*
22  *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
23  */
24
25 /*
26 $Revision: 1.45 $
27 $Date: 2010/08/19 13:42:30 $
28 $Author: faust $
29 */
30
31 #include <cstring>
32 #include <cerrno>
33 #include <string>
34
35 #include "settings.h"
36 #include "stg_logger.h"
37 #include "dotconfpp.h"
38
39 using namespace std;
40
41 //-----------------------------------------------------------------------------
42 SETTINGS::SETTINGS()
43     : confDir("/etc/stargazer"),
44       scriptsDir("/etc/stargazer"),
45       pidFile("/var/run/stargazer.pid"),
46       monitoring(false),
47       detailStatWritePeriod(dsPeriod_1_6),
48       statWritePeriod(10),
49       stgExecMsgKey(5555),
50       executersNum(1),
51       fullFee(false),
52       dayFee(0),
53       dayResetTraff(0),
54       spreadFee(false),
55       freeMbAllowInet(false),
56       dayFeeIsLastDay(false),
57       writeFreeMbTraffCost(false),
58       showFeeInCash(true),
59       messageTimeout(0),
60       logger(GetStgLogger())
61 {
62 }
63 //-----------------------------------------------------------------------------
64 SETTINGS::SETTINGS(const std::string & cd)
65     : confDir(cd),
66       scriptsDir(cd),
67       monitoring(false),
68       detailStatWritePeriod(dsPeriod_1_6),
69       statWritePeriod(10),
70       stgExecMsgKey(5555),
71       executersNum(1),
72       fullFee(false),
73       dayFee(0),
74       dayResetTraff(0),
75       spreadFee(false),
76       freeMbAllowInet(false),
77       dayFeeIsLastDay(false),
78       writeFreeMbTraffCost(false),
79       showFeeInCash(true),
80       messageTimeout(0),
81       logger(GetStgLogger())
82 {
83 }
84 //-----------------------------------------------------------------------------
85 SETTINGS::SETTINGS(const SETTINGS & rval)
86     : confDir(rval.confDir),
87       scriptsDir(rval.scriptsDir),
88       pidFile(rval.pidFile),
89       monitoring(rval.monitoring),
90       detailStatWritePeriod(dsPeriod_1_6),
91       statWritePeriod(10),
92       stgExecMsgKey(rval.stgExecMsgKey),
93       executersNum(rval.executersNum),
94       fullFee(rval.fullFee),
95       dayFee(0),
96       dayResetTraff(0),
97       spreadFee(rval.spreadFee),
98       freeMbAllowInet(false),
99       dayFeeIsLastDay(false),
100       writeFreeMbTraffCost(false),
101       showFeeInCash(rval.showFeeInCash),
102       messageTimeout(rval.messageTimeout),
103       logger(GetStgLogger())
104 {
105 }
106 //-----------------------------------------------------------------------------
107 SETTINGS::~SETTINGS()
108 {
109 }
110 //-----------------------------------------------------------------------------
111 int SETTINGS::ParseYesNo(const string & value, bool * val)
112 {
113 if (0 == strcasecmp(value.c_str(), "yes"))
114     {
115     *val = true;
116     return 0;
117     }
118 if (0 == strcasecmp(value.c_str(), "no"))
119     {
120     *val = false;
121     return 0;
122     }
123
124 strError = "Incorrect value \'" + value + "\'.";
125 return -1;
126 }
127 //-----------------------------------------------------------------------------
128 int SETTINGS::ParseInt(const string & value, int * val)
129 {
130 if (str2x<int>(value, *val))
131     {
132     strError = "Cannot convert \'" + value + "\' to integer.";
133     return -1;
134     }
135 return 0;
136 }
137 //-----------------------------------------------------------------------------
138 int SETTINGS::ParseUnsigned(const string & value, unsigned * val)
139 {
140 if (str2x<unsigned>(value, *val))
141     {
142     strError = "Cannot convert \'" + value + "\' to unsigned integer.";
143     return -1;
144     }
145 return 0;
146 }
147 //-----------------------------------------------------------------------------
148 int SETTINGS::ParseIntInRange(const string & value, int min, int max, int * val)
149 {
150 if (ParseInt(value, val) != 0)
151     return -1;
152
153 if (*val < min || *val > max)
154     {
155     strError = "Value \'" + value + "\' out of range.";
156     return -1;
157     }
158
159 return 0;
160 }
161 //-----------------------------------------------------------------------------
162 int SETTINGS::ParseUnsignedInRange(const string & value, unsigned min, unsigned max, unsigned * val)
163 {
164 if (ParseUnsigned(value, val) != 0)
165     return -1;
166
167 if (*val < min || *val > max)
168     {
169     strError = "Value \'" + value + "\' out of range.";
170     return -1;
171     }
172
173 return 0;
174 }
175 //-----------------------------------------------------------------------------
176 int SETTINGS::ParseModuleSettings(const DOTCONFDocumentNode * node, vector<PARAM_VALUE> * params)
177 {
178 const DOTCONFDocumentNode * childNode;
179 PARAM_VALUE pv;
180 const char * value;
181
182 pv.param = node->getName();
183
184 if (node->getValue(1))
185     {
186     strError = "Unexpected value \'" + string(node->getValue(1)) + "\'.";
187     return -1;
188     }
189
190 value = node->getValue(0);
191
192 if (!value)
193     {
194     strError = "Module name expected.";
195     return -1;
196     }
197
198 childNode = node->getChildNode();
199 while (childNode)
200     {
201     pv.param = childNode->getName();
202     int i = 0;
203     while ((value = childNode->getValue(i++)) != NULL)
204         {
205         pv.value.push_back(value);
206         }
207     params->push_back(pv);
208     pv.value.clear();
209     childNode = childNode->getNextNode();
210     }
211
212 return 0;
213 }
214 //-----------------------------------------------------------------------------
215 void SETTINGS::ErrorCallback(void * data, const char * buf)
216 {
217     printfd(__FILE__, buf);
218     SETTINGS * settings = static_cast<SETTINGS *>(data);
219     settings->logger(buf);
220 }
221 //-----------------------------------------------------------------------------
222 int SETTINGS::ReadSettings()
223 {
224 const char * requiredOptions[] = {
225     "ModulesPath",
226     "Modules",
227     "StoreModule",
228     "Rules",
229     "LogFile",
230     "DetailStatWritePeriod",
231     "DayFee",
232     "DayResetTraff",
233     "SpreadFee",
234     "FreeMbAllowInet",
235     "DayFeeIsLastDay",
236     "WriteFreeMbTraffCost",
237     NULL
238     };
239 int storeModulesCount = 0;
240 modulesSettings.clear();
241
242 DOTCONFDocument conf(DOTCONFDocument::CASEINSENSITIVE);
243 conf.setErrorCallback(SETTINGS::ErrorCallback, this);
244 conf.setRequiredOptionNames(requiredOptions);
245 string confFile = confDir + "/stargazer.conf";
246
247 if(conf.setContent(confFile.c_str()) != 0)
248     {
249     strError = "Cannot read file " + confFile;
250     return -1;
251     }
252
253 const DOTCONFDocumentNode * node = conf.getFirstNode();
254
255 while (node)
256     {
257     if (strcasecmp(node->getName(), "ScriptDir") == 0)
258         {
259         scriptsDir = node->getValue(0);
260         }
261
262     if (strcasecmp(node->getName(), "LogFile") == 0)
263         {
264         logFile = node->getValue(0);
265         }
266
267     if (strcasecmp(node->getName(), "PIDFile") == 0)
268         {
269         pidFile = node->getValue(0);
270         }
271
272     if (strcasecmp(node->getName(), "ModulesPath") == 0)
273         {
274         modulesPath = node->getValue(0);
275         }
276
277     if (strcasecmp(node->getName(), "Rules") == 0)
278         {
279         rules = node->getValue(0);
280         }
281
282     if (strcasecmp(node->getName(), "DetailStatWritePeriod") == 0)
283         {
284         if (ParseDetailStatWritePeriod(node->getValue(0)) != 0)
285             {
286             strError = "Incorrect DetailStatWritePeriod value: \'" + string(node->getValue(0)) + "\'";
287             return -1;
288             }
289         }
290
291     if (strcasecmp(node->getName(), "StatWritePeriod") == 0)
292         {
293         if (ParseUnsignedInRange(node->getValue(0), 1, 1440, &statWritePeriod) != 0)
294             {
295             strError = "Incorrect StatWritePeriod value: \'" + string(node->getValue(0)) + "\'";
296             return -1;
297             }
298         }
299
300     if (strcasecmp(node->getName(), "ExecMsgKey") == 0)
301         {
302         if (ParseInt(node->getValue(0), &stgExecMsgKey) != 0)
303             {
304             strError = "Incorrect ExecMsgKey value: \'" + string(node->getValue(0)) + "\'";
305             return -1;
306             }
307         }
308
309     if (strcasecmp(node->getName(), "ExecutersNum") == 0)
310         {
311         if (ParseUnsignedInRange(node->getValue(0), 1, 1024, &executersNum) != 0)
312             {
313             strError = "Incorrect ExecutersNum value: \'" + string(node->getValue(0)) + "\'";
314             return -1;
315             }
316         }
317
318     if (strcasecmp(node->getName(), "DayFee") == 0)
319         {
320         if (ParseUnsignedInRange(node->getValue(0), 0, 31, &dayFee) != 0)
321             {
322             strError = "Incorrect DayFee value: \'" + string(node->getValue(0)) + "\'";
323             return -1;
324             }
325         }
326
327     if (strcasecmp(node->getName(), "FullFee") == 0)
328         {
329         if (ParseYesNo(node->getValue(0), &fullFee) != 0)
330             {
331             strError = "Incorrect FullFee value: \'" + string(node->getValue(0)) + "\'";
332             return -1;
333             }
334         }
335
336     if (strcasecmp(node->getName(), "DayResetTraff") == 0)
337         {
338         if (ParseUnsignedInRange(node->getValue(0), 0, 31, &dayResetTraff) != 0)
339             {
340             strError = "Incorrect DayResetTraff value: \'" + string(node->getValue(0)) + "\'";
341             return -1;
342             }
343         }
344
345     if (strcasecmp(node->getName(), "SpreadFee") == 0)
346         {
347         if (ParseYesNo(node->getValue(0), &spreadFee) != 0)
348             {
349             strError = "Incorrect SpreadFee value: \'" + string(node->getValue(0)) + "\'";
350             return -1;
351             }
352         }
353
354     if (strcasecmp(node->getName(), "FreeMbAllowInet") == 0)
355         {
356         if (ParseYesNo(node->getValue(0), &freeMbAllowInet) != 0)
357             {
358             strError = "Incorrect FreeMbAllowInet value: \'" + string(node->getValue(0)) + "\'";
359             return -1;
360             }
361         }
362
363     if (strcasecmp(node->getName(), "DayFeeIsLastDay") == 0)
364         {
365         if (ParseYesNo(node->getValue(0), &dayFeeIsLastDay) != 0)
366             {
367             strError = "Incorrect DayFeeIsLastDay value: \'" + string(node->getValue(0)) + "\'";
368             return -1;
369             }
370         }
371
372     if (strcasecmp(node->getName(), "WriteFreeMbTraffCost") == 0)
373         {
374         if (ParseYesNo(node->getValue(0), &writeFreeMbTraffCost) != 0)
375             {
376             strError = "Incorrect WriteFreeMbTraffCost value: \'" + string(node->getValue(0)) + "\'";
377             return -1;
378             }
379         }
380
381     if (strcasecmp(node->getName(), "ShowFeeInCash") == 0)
382         {
383         if (ParseYesNo(node->getValue(0), &showFeeInCash) != 0)
384             {
385             strError = "Incorrect ShowFeeInCash value: \'" + string(node->getValue(0)) + "\'";
386             return -1;
387             }
388         }
389
390     if (strcasecmp(node->getName(), "MonitorDir") == 0)
391         {
392         monitorDir = node->getValue(0);
393         struct stat stat;
394         monitoring = false;
395
396         if (!lstat(monitorDir.c_str(), &stat) && S_ISDIR(stat.st_mode))
397             {
398             monitoring = true;
399             }
400         }
401
402     if (strcasecmp(node->getName(), "MessageTimeout") == 0)
403         {
404         if (ParseUnsigned(node->getValue(0), &messageTimeout) != 0)
405             {
406             strError = "Incorrect MessageTimeout value: \'" + string(node->getValue(0)) + "\'";
407             return -1;
408             }
409         }
410
411     if (strcasecmp(node->getName(), "DirNames") == 0)
412         {
413         const DOTCONFDocumentNode * child = node->getChildNode();
414         if (child)
415             {
416             const DOTCONFDocumentNode * dirNameNode;
417             for (int i = 0; i < DIR_NUM; i++)
418                 {
419                 char strDirName[12];
420                 sprintf(strDirName, "DirName%d", i);
421                 dirNameNode = conf.findNode(strDirName, node);
422                 if (dirNameNode && dirNameNode->getValue(0))
423                     {
424                     dirName[i] = dirNameNode->getValue(0);
425                     }
426                 }
427             }
428         }
429
430     if (strcasecmp(node->getName(), "StoreModule") == 0)
431         {
432         if (node->getValue(1))
433             {
434             strError = "Unexpected \'" + string(node->getValue(1)) + "\'.";
435             return -1;
436             }
437
438         if (storeModulesCount)
439             {
440             strError = "Should be only one StoreModule.";
441             return -1;
442             }
443         storeModulesCount++;
444
445         storeModuleSettings.moduleName = node->getValue(0);
446         ParseModuleSettings(node, &storeModuleSettings.moduleParams);
447         }
448
449     if (strcasecmp(node->getName(), "Modules") == 0)
450         {
451         if (node->getValue(0))
452             {
453             strError = "Unexpected \'" + string(node->getValue(0)) + "\'.";
454             return -1;
455             }
456         const DOTCONFDocumentNode * child = node->getChildNode();
457         while (child)
458             {
459             if (strcasecmp(child->getName(), "Module") != 0)
460                 {
461                 child = child->getNextNode();
462                 continue;
463                 }
464             MODULE_SETTINGS modSettings;
465             modSettings.moduleParams.clear();
466             modSettings.moduleName = child->getValue();
467
468             ParseModuleSettings(child, &modSettings.moduleParams);
469
470             modulesSettings.push_back(modSettings);
471
472             child = child->getNextNode();
473             }
474         }
475
476     node = node->getNextNode();
477     }
478
479 return 0;
480 }
481 //-----------------------------------------------------------------------------
482 int SETTINGS::ParseDetailStatWritePeriod(const string & detailStatPeriodStr)
483 {
484 if (detailStatPeriodStr == "1")
485     {
486     detailStatWritePeriod = dsPeriod_1;
487     return 0;
488     }
489 else if (detailStatPeriodStr == "1/2")
490     {
491     detailStatWritePeriod = dsPeriod_1_2;
492     return 0;
493     }
494 else if (detailStatPeriodStr == "1/4")
495     {
496     detailStatWritePeriod = dsPeriod_1_4;
497     return 0;
498     }
499 else if (detailStatPeriodStr == "1/6")
500     {
501     detailStatWritePeriod = dsPeriod_1_6;
502     return 0;
503     }
504
505 return -1;
506 }
507 //-----------------------------------------------------------------------------