]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/store/postgresql/postgresql_store_tariffs.cpp
Patch from SpiderX <spiderx@spiderx.dp.ua> - path to FreeRADIUS plugins.
[stg.git] / projects / stargazer / plugins / store / postgresql / postgresql_store_tariffs.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  *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
19  */
20
21 /*
22  *  Tariffs manipulation methods
23  *
24  *  $Revision: 1.2 $
25  *  $Date: 2009/06/09 12:32:40 $
26  *
27  */
28
29 #include <string>
30 #include <vector>
31 #include <sstream>
32 #include <cmath>
33
34 #include <libpq-fe.h>
35
36 #include "postgresql_store.h"
37 #include "stg/locker.h"
38
39 //-----------------------------------------------------------------------------
40 int POSTGRESQL_STORE::GetTariffsList(vector<string> * tariffsList) const
41 {
42 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
43
44 if (PQstatus(connection) != CONNECTION_OK)
45     {
46     printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
47     if (Reset())
48         {
49         strError = "Connection lost";
50         printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): '%s'\n", strError.c_str());
51         return -1;
52         }
53     }
54
55 PGresult * result;
56
57 if (StartTransaction())
58     {
59     printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to start transaction'\n");
60     return -1;
61     }
62
63 result = PQexec(connection, "SELECT name FROM tb_tariffs");
64
65 if (PQresultStatus(result) != PGRES_TUPLES_OK)
66     {
67     strError = PQresultErrorMessage(result);
68     PQclear(result);
69     printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): '%s'\n", strError.c_str());
70     if (RollbackTransaction())
71         {
72         printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to rollback transaction'\n");
73         }
74     return -1;
75     }
76
77 int tuples = PQntuples(result);
78
79 for (int i = 0; i < tuples; ++i)
80     {
81     tariffsList->push_back(PQgetvalue(result, i, 0));
82     }
83
84 PQclear(result);
85
86 if (CommitTransaction())
87     {
88     printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to commit transaction'\n");
89     return -1;
90     }
91
92 return 0;
93 }
94
95 //-----------------------------------------------------------------------------
96 int POSTGRESQL_STORE::AddTariff(const string & name) const
97 {
98 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
99
100 if (PQstatus(connection) != CONNECTION_OK)
101     {
102     printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
103     if (Reset())
104         {
105         strError = "Connection lost";
106         printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): '%s'\n", strError.c_str());
107         return -1;
108         }
109     }
110
111 PGresult * result;
112
113 if (StartTransaction())
114     {
115     printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to start transaction'\n");
116     return -1;
117     }
118
119 std::string ename = name;
120
121 if (EscapeString(ename))
122     {
123     printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to escape name'\n");
124     if (RollbackTransaction())
125         {
126         printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
127         }
128     return -1;
129     }
130
131 std::stringstream query;
132 query << "SELECT sp_add_tariff('" << ename << "', " << DIR_NUM << ")";
133
134 result = PQexec(connection, query.str().c_str());
135
136 if (PQresultStatus(result) != PGRES_TUPLES_OK)
137     {
138     strError = PQresultErrorMessage(result);
139     PQclear(result);
140     printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): '%s'\n", strError.c_str());
141     if (RollbackTransaction())
142         {
143         printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
144         }
145     return -1;
146     }
147
148 PQclear(result);
149
150 if (CommitTransaction())
151     {
152     printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to commit transaction'\n");
153     return -1;
154     }
155
156 return 0;
157 }
158 //-----------------------------------------------------------------------------
159 int POSTGRESQL_STORE::DelTariff(const string & name) const
160 {
161 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
162
163 if (PQstatus(connection) != CONNECTION_OK)
164     {
165     printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
166     if (Reset())
167         {
168         strError = "Connection lost";
169         printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): '%s'\n", strError.c_str());
170         return -1;
171         }
172     }
173
174 PGresult * result;
175
176 if (StartTransaction())
177     {
178     printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to start transaction'\n");
179     return -1;
180     }
181
182 std::string ename = name;
183
184 if (EscapeString(ename))
185     {
186     printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to escape name'\n");
187     if (RollbackTransaction())
188         {
189         printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
190         }
191     return -1;
192     }
193
194 std::stringstream query;
195 query << "DELETE FROM tb_tariffs WHERE name = '" << ename << "'";
196
197 result = PQexec(connection, query.str().c_str());
198
199 if (PQresultStatus(result) != PGRES_COMMAND_OK)
200     {
201     strError = PQresultErrorMessage(result);
202     PQclear(result);
203     printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): '%s'\n", strError.c_str());
204     if (RollbackTransaction())
205         {
206         printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to rollback transaction'\n");
207         }
208     return -1;
209     }
210
211 PQclear(result);
212
213 if (CommitTransaction())
214     {
215     printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to commit transaction'\n");
216     return -1;
217     }
218
219 return 0;
220 }
221 //-----------------------------------------------------------------------------
222 int POSTGRESQL_STORE::SaveTariff(const TARIFF_DATA & td,
223                                  const string & tariffName) const
224 {
225 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
226
227 if (PQstatus(connection) != CONNECTION_OK)
228     {
229     printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
230     if (Reset())
231         {
232         strError = "Connection lost";
233         printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
234         return -1;
235         }
236     }
237
238 PGresult * result;
239
240 if (StartTransaction())
241     {
242     printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to start transaction'\n");
243     return -1;
244     }
245
246 std::string ename = tariffName;
247
248 if (EscapeString(ename))
249     {
250     printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to escape name'\n");
251     if (RollbackTransaction())
252         {
253         printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
254         }
255     return -1;
256     }
257
258 int32_t id, i;
259 double pda, pdb, pna, pnb;
260 int threshold;
261
262 std::stringstream query;
263 query << "SELECT pk_tariff FROM tb_tariffs WHERE name = '" << ename << "'";
264
265 result = PQexec(connection, query.str().c_str());
266
267 if (PQresultStatus(result) != PGRES_TUPLES_OK)
268     {
269     strError = PQresultErrorMessage(result);
270     PQclear(result);
271     printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
272     if (RollbackTransaction())
273         {
274         printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
275         }
276     return -1;
277     }
278
279 int tuples = PQntuples(result);
280
281 if (tuples != 1)
282     {
283     strError = "Failed to fetch tariff ID";
284     printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
285     PQclear(result);
286     if (RollbackTransaction())
287         {
288         printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
289         }
290     return -1;
291     }
292
293 std::stringstream tuple;
294 tuple << PQgetvalue(result, 0, 0);
295
296 PQclear(result);
297
298 tuple >> id;
299
300 query.str("");
301 query << "UPDATE tb_tariffs SET \
302               fee = " << td.tariffConf.fee << ", \
303               free = " << td.tariffConf.free << ", \
304               passive_cost = " << td.tariffConf.passiveCost << ", \
305               traff_type = " << td.tariffConf.traffType << " \
306           WHERE pk_tariff = " << id;
307
308 result = PQexec(connection, query.str().c_str());
309
310 if (PQresultStatus(result) != PGRES_COMMAND_OK)
311     {
312     strError = PQresultErrorMessage(result);
313     PQclear(result);
314     printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
315     if (RollbackTransaction())
316         {
317         printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
318         }
319     return -1;
320     }
321
322 PQclear(result);
323
324 for(i = 0; i < DIR_NUM; i++)
325     {
326
327     pda = td.dirPrice[i].priceDayA * 1024 * 1024;
328     pdb = td.dirPrice[i].priceDayB * 1024 * 1024;
329
330     if (td.dirPrice[i].singlePrice)
331         {
332         pna = pda;
333         pnb = pdb;
334         }
335     else
336         {
337         pna = td.dirPrice[i].priceNightA * 1024 * 1024;
338         pnb = td.dirPrice[i].priceNightB * 1024 * 1024;
339         }
340
341     if (td.dirPrice[i].noDiscount)
342         {
343         threshold = 0xffFFffFF;
344         }
345     else
346         {
347         threshold = td.dirPrice[i].threshold;
348         }
349
350     std::stringstream query;
351     query << "UPDATE tb_tariffs_params SET \
352                   price_day_a = " << pda << ", \
353                   price_day_b = " << pdb << ", \
354                   price_night_a = " << pna << ", \
355                   price_night_b = " << pnb << ", \
356                   threshold = " << threshold << ", \
357                   time_day_begins = CAST('" << td.dirPrice[i].hDay
358                                             << ":"
359                                             << td.dirPrice[i].mDay << "' AS TIME), \
360                   time_day_ends = CAST('" << td.dirPrice[i].hNight
361                                           << ":"
362                                           << td.dirPrice[i].mNight << "' AS TIME) \
363              WHERE fk_tariff = " << id << " AND dir_num = " << i;
364
365     result = PQexec(connection, query.str().c_str());
366
367     if (PQresultStatus(result) != PGRES_COMMAND_OK)
368         {
369         strError = PQresultErrorMessage(result);
370         PQclear(result);
371         printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
372         if (RollbackTransaction())
373             {
374             printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
375             }
376         return -1;
377         }
378
379     PQclear(result);
380     }
381
382 if (CommitTransaction())
383     {
384     printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to commit transaction'\n");
385     return -1;
386     }
387
388 return 0;
389 }
390 //-----------------------------------------------------------------------------
391 int POSTGRESQL_STORE::RestoreTariff(TARIFF_DATA * td,
392                                   const string & tariffName) const
393 {
394 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
395
396 if (PQstatus(connection) != CONNECTION_OK)
397     {
398     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
399     if (Reset())
400         {
401         strError = "Connection lost";
402         printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
403         return -1;
404         }
405     }
406
407 PGresult * result;
408
409 if (StartTransaction())
410     {
411     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to start transaction'\n");
412     return -1;
413     }
414
415 std::string ename = tariffName;
416
417 if (EscapeString(ename))
418     {
419     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to escape name'\n");
420     if (RollbackTransaction())
421         {
422         printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
423         }
424     return -1;
425     }
426
427 td->tariffConf.name = tariffName;
428
429 std::stringstream query;
430 query << "SELECT pk_tariff, \
431                  fee, \
432                  free, \
433                  passive_cost, \
434                  traff_type \
435           FROM tb_tariffs WHERE name = '" << ename << "'";
436
437 result = PQexec(connection, query.str().c_str());
438
439 if (PQresultStatus(result) != PGRES_TUPLES_OK)
440     {
441     strError = PQresultErrorMessage(result);
442     PQclear(result);
443     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
444     if (RollbackTransaction())
445         {
446         printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
447         }
448     return -1;
449     }
450
451 int tuples = PQntuples(result);
452
453 if (tuples != 1)
454     {
455     strError = "Failed to fetch tariff data";
456     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
457     PQclear(result);
458     if (RollbackTransaction())
459         {
460         printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
461         }
462     return -1;
463     }
464
465 std::stringstream tuple;
466 tuple << PQgetvalue(result, 0, 0) << " ";
467 tuple << PQgetvalue(result, 0, 1) << " ";
468 tuple << PQgetvalue(result, 0, 2) << " ";
469 tuple << PQgetvalue(result, 0, 3) << " ";
470 tuple << PQgetvalue(result, 0, 4) << " ";
471
472 int id;
473 tuple >> id;
474 tuple >> td->tariffConf.fee;
475 tuple >> td->tariffConf.free;
476 tuple >> td->tariffConf.passiveCost;
477 tuple >> td->tariffConf.traffType;
478
479 PQclear(result);
480
481 query.str("");
482 query << "SELECT dir_num, \
483                  price_day_a, \
484                  price_day_b, \
485                  price_night_a, \
486                  price_night_b, \
487                  threshold, \
488                  EXTRACT(hour FROM time_day_begins), \
489                  EXTRACT(minute FROM time_day_begins), \
490                  EXTRACT(hour FROM time_day_ends), \
491                  EXTRACT(minute FROM time_day_ends) \
492           FROM tb_tariffs_params \
493           WHERE fk_tariff = " << id;
494
495 result = PQexec(connection, query.str().c_str());
496
497 if (PQresultStatus(result) != PGRES_TUPLES_OK)
498     {
499     strError = PQresultErrorMessage(result);
500     PQclear(result);
501     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
502     if (RollbackTransaction())
503         {
504         printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
505         }
506     return -1;
507     }
508
509 tuples = PQntuples(result);
510
511 if (tuples != DIR_NUM)
512     {
513     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Tariff params count and DIR_NUM does not feet (wanted %d, actually %d)'\n", DIR_NUM, tuples);
514     }
515
516 for (int i = 0; i < std::min(tuples, DIR_NUM); ++i)
517     {
518     std::stringstream tuple;
519     tuple << PQgetvalue(result, i, 0) << " ";
520     tuple << PQgetvalue(result, i, 1) << " ";
521     tuple << PQgetvalue(result, i, 2) << " ";
522     tuple << PQgetvalue(result, i, 3) << " ";
523     tuple << PQgetvalue(result, i, 4) << " ";
524     tuple << PQgetvalue(result, i, 5) << " ";
525     tuple << PQgetvalue(result, i, 6) << " ";
526     tuple << PQgetvalue(result, i, 7) << " ";
527     tuple << PQgetvalue(result, i, 8) << " ";
528     tuple << PQgetvalue(result, i, 9) << " ";
529
530     int dir;
531
532     tuple >> dir;
533     tuple >> td->dirPrice[dir].priceDayA;
534     td->dirPrice[dir].priceDayA /= 1024 * 1024;
535     tuple >> td->dirPrice[dir].priceDayB;
536     td->dirPrice[dir].priceDayB /= 1024 * 1024;
537     tuple >> td->dirPrice[dir].priceNightA;
538     td->dirPrice[dir].priceNightA /= 1024 * 1024;
539     tuple >> td->dirPrice[dir].priceNightB;
540     td->dirPrice[dir].priceNightB /= 1024 * 1024;
541     tuple >> td->dirPrice[dir].threshold;
542     tuple >> td->dirPrice[dir].hDay;
543     tuple >> td->dirPrice[dir].mDay;
544     tuple >> td->dirPrice[dir].hNight;
545     tuple >> td->dirPrice[dir].mNight;
546
547     if (std::fabs(td->dirPrice[dir].priceDayA - td->dirPrice[dir].priceNightA) > 1.0e-3 &&
548         std::fabs(td->dirPrice[dir].priceDayB - td->dirPrice[dir].priceNightB) > 1.0e-3)
549         {
550         td->dirPrice[dir].singlePrice = true;
551         }
552     else
553         {
554         td->dirPrice[dir].singlePrice = false;
555         }
556     if (td->dirPrice[dir].threshold == (int)0xffFFffFF)
557         {
558         td->dirPrice[dir].noDiscount = true;
559         }
560     else
561         {
562
563         td->dirPrice[dir].noDiscount = false;
564         }
565
566     }
567
568 PQclear(result);
569
570 if (CommitTransaction())
571     {
572     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to commit transaction'\n");
573     return -1;
574     }
575
576 return 0;
577 }
578 //-----------------------------------------------------------------------------
579