]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/store/firebird/firebird_store_users.cpp
2e92603ea3a201c5ab87c405bbc8637e40d77268
[stg.git] / projects / stargazer / plugins / store / firebird / firebird_store_users.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  *  User manipulation methods
23  *
24  *  $Revision: 1.19 $
25  *  $Date: 2010/01/19 11:07:25 $
26  *
27  */
28
29 #include "stg/const.h"
30 #include "firebird_store.h"
31 #include "stg/ibpp.h"
32
33 //-----------------------------------------------------------------------------
34 int FIREBIRD_STORE::GetUsersList(std::vector<std::string> * usersList) const
35 {
36 STG_LOCKER lock(&mutex);
37
38 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
39 IBPP::Statement st = IBPP::StatementFactory(db, tr);
40
41 std::string name;
42
43 try
44     {
45     tr->Start();
46     st->Execute("select name from tb_users");
47     while (st->Fetch())
48         {
49         st->Get(1, name);
50         usersList->push_back(name);
51         }
52     tr->Commit();
53     }
54
55 catch (IBPP::Exception & ex)
56     {
57     tr->Rollback();
58     strError = "IBPP exception";
59     printfd(__FILE__, ex.what());
60     return -1;
61     }
62
63 return 0;
64 }
65 //-----------------------------------------------------------------------------
66 int FIREBIRD_STORE::AddUser(const std::string & name) const
67 {
68 STG_LOCKER lock(&mutex);
69
70 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
71 IBPP::Statement st = IBPP::StatementFactory(db, tr);
72
73 try
74     {
75     tr->Start();
76     st->Prepare("execute procedure sp_add_user(?, ?)");
77     st->Set(1, name);
78     st->Set(2, DIR_NUM);
79     st->Execute();
80     tr->Commit();
81     }
82
83 catch (IBPP::Exception & ex)
84     {
85     tr->Rollback();
86     strError = "IBPP exception";
87     printfd(__FILE__, ex.what());
88     return -1;
89     }
90
91 return 0;
92 }
93 //-----------------------------------------------------------------------------
94 int FIREBIRD_STORE::DelUser(const std::string & login) const
95 {
96 STG_LOCKER lock(&mutex);
97
98 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
99 IBPP::Statement st = IBPP::StatementFactory(db, tr);
100
101 try
102     {
103     tr->Start();
104     st->Prepare("execute procedure sp_delete_user(?)");
105     st->Set(1, login);
106     st->Execute();
107     tr->Commit();
108     }
109
110 catch (IBPP::Exception & ex)
111     {
112     tr->Rollback();
113     strError = "IBPP exception";
114     printfd(__FILE__, ex.what());
115     return -1;
116     }
117
118 return 0;
119 }
120 //-----------------------------------------------------------------------------
121 int FIREBIRD_STORE::SaveUserStat(const USER_STAT & stat,
122                                  const std::string & login) const
123 {
124 STG_LOCKER lock(&mutex);
125
126 return SaveStat(stat, login);
127 }
128 //-----------------------------------------------------------------------------
129 int FIREBIRD_STORE::SaveStat(const USER_STAT & stat,
130                              const std::string & login,
131                              int year,
132                              int month) const
133 {
134 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
135 IBPP::Statement st = IBPP::StatementFactory(db, tr);
136
137 try
138     {
139     tr->Start();
140     st->Prepare("select pk_user from tb_users where name = ?");
141     st->Set(1, login);
142     st->Execute();
143     if (!st->Fetch())
144     {
145     strError = "User \"" + login + "\" not found in database";
146     printfd(__FILE__, "User '%s' not found in database\n", login.c_str());
147     tr->Rollback();
148     return -1;
149     }
150     int32_t uid = Get<int32_t>(st, 1);
151     st->Close();
152     st->Prepare("select first 1 pk_stat from tb_stats where fk_user = ? order by stats_date desc");
153     st->Set(1, uid);
154     st->Execute();
155     if (!st->Fetch())
156     {
157     tr->Rollback();
158     strError = "No stat info for user \"" + login + "\"";
159     printfd(__FILE__, "No stat info for user '%s'\n", login.c_str());
160     return -1;
161     }
162     int32_t sid;
163     st->Get(1, sid);
164     st->Close();
165
166     IBPP::Timestamp actTime;
167     time_t2ts(stat.lastActivityTime, &actTime);
168     IBPP::Timestamp addTime;
169     time_t2ts(stat.lastCashAddTime, &addTime);
170     IBPP::Date dt;
171     if (year != 0)
172         ym2date(year, month, &dt);
173     else
174         dt.Today();
175
176     st->Prepare("update tb_stats set \
177                     cash = ?, \
178                     free_mb = ?, \
179                     last_activity_time = ?, \
180                     last_cash_add = ?, \
181                     last_cash_add_time = ?, \
182                     passive_time = ?, \
183                     stats_date = ? \
184                  where pk_stat = ?");
185
186     st->Set(1, stat.cash);
187     st->Set(2, stat.freeMb);
188     st->Set(3, actTime);
189     st->Set(4, stat.lastCashAdd);
190     st->Set(5, addTime);
191     st->Set(6, (int32_t)stat.passiveTime);
192     st->Set(7, dt);
193     st->Set(8, sid);
194
195     st->Execute();
196     st->Close();
197
198     for(int i = 0; i < DIR_NUM; i++)
199         {
200         st->Prepare("update tb_stats_traffic set \
201                         upload = ?, \
202                         download = ? \
203                      where fk_stat = ? and dir_num = ?");
204         st->Set(1, (int64_t)stat.monthUp[i]);
205         st->Set(2, (int64_t)stat.monthDown[i]);
206         st->Set(3, sid);
207         st->Set(4, i);
208         st->Execute();
209         st->Close();
210         }
211
212     tr->Commit();
213     }
214
215 catch (IBPP::Exception & ex)
216     {
217     tr->Rollback();
218     strError = "IBPP exception";
219     printfd(__FILE__, ex.what());
220     return -1;
221     }
222
223 return 0;
224 }
225 //-----------------------------------------------------------------------------
226 int FIREBIRD_STORE::SaveUserConf(const USER_CONF & conf,
227                                  const std::string & login) const
228 {
229 STG_LOCKER lock(&mutex);
230
231 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
232 IBPP::Statement st = IBPP::StatementFactory(db, tr);
233
234 try
235     {
236     tr->Start();
237     st->Prepare("select pk_user from tb_users where name = ?");
238     st->Set(1, login);
239     st->Execute();
240     if (!st->Fetch())
241         {
242         strError = "User \"" + login + "\" not found in database";
243         printfd(__FILE__, "User '%s' not found in database\n", login.c_str());
244         tr->Rollback();
245         return -1;
246         }
247     int32_t uid;
248     st->Get(1, uid);
249     st->Close();
250
251     IBPP::Timestamp creditExpire;
252     time_t2ts(conf.creditExpire, &creditExpire);
253
254     st->Prepare("update tb_users set \
255                     address = ?, \
256                     always_online = ?, \
257                     credit = ?, \
258                     credit_expire = ?, \
259                     disabled = ?, \
260                     disabled_detail_stat = ?, \
261                     email = ?, \
262                     grp = ?, \
263                     note = ?, \
264                     passive = ?, \
265                     passwd = ?, \
266                     phone = ?, \
267                     fk_tariff = (select pk_tariff from tb_tariffs \
268                                  where name = ?), \
269                     fk_tariff_change = (select pk_tariff from tb_tariffs \
270                                         where name = ?), \
271                     fk_corporation = (select pk_corporation from tb_corporations \
272                                       where name = ?), \
273                     real_name = ? \
274                  where pk_user = ?");
275
276     st->Set(1, conf.address);
277     st->Set(2, (bool)conf.alwaysOnline);
278     st->Set(3, conf.credit);
279     st->Set(4, creditExpire);
280     st->Set(5, (bool)conf.disabled);
281     st->Set(6, (bool)conf.disabledDetailStat);
282     st->Set(7, conf.email);
283     st->Set(8, conf.group);
284     st->Set(9, conf.note);
285     st->Set(10, (bool)conf.passive);
286     st->Set(11, conf.password);
287     st->Set(12, conf.phone);
288     st->Set(13, conf.tariffName);
289     st->Set(14, conf.nextTariff);
290     st->Set(15, conf.corp);
291     st->Set(16, conf.realName);
292     st->Set(17, uid);
293
294     st->Execute();
295     st->Close();
296
297     st->Prepare("delete from tb_users_services where fk_user = ?");
298     st->Set(1, uid);
299     st->Execute();
300     st->Close();
301
302     st->Prepare("insert into tb_users_services (fk_user, fk_service) \
303                     values (?, (select pk_service from tb_services \
304                                 where name = ?))");
305     for(std::vector<std::string>::const_iterator it = conf.service.begin(); it != conf.service.end(); ++it)
306         {
307         st->Set(1, uid);
308         st->Set(2, *it);
309         st->Execute();
310         }
311     st->Close();
312
313     st->Prepare("delete from tb_users_data where fk_user = ?");
314     st->Set(1, uid);
315     st->Execute();
316     st->Close();
317
318     int i = 0;
319     st->Prepare("insert into tb_users_data (fk_user, data, num) values (?, ?, ?)");
320     for (std::vector<std::string>::const_iterator it = conf.userdata.begin(); it != conf.userdata.end(); ++it)
321         {
322         st->Set(1, uid);
323         st->Set(2, *it);
324         st->Set(3, i++);
325         st->Execute();
326         }
327     st->Close();
328
329     st->Prepare("delete from tb_allowed_ip where fk_user = ?");
330     st->Set(1, uid);
331     st->Execute();
332
333     st->Prepare("insert into tb_allowed_ip (fk_user, ip, mask) values (?, ?, ?)");
334     for(size_t i = 0; i < conf.ips.Count(); i++)
335         {
336         st->Set(1, uid);
337         st->Set(2, (int32_t)conf.ips[i].ip);
338         st->Set(3, (int32_t)conf.ips[i].mask);
339         st->Execute();
340         }
341     tr->Commit();
342     }
343 catch (IBPP::Exception & ex)
344     {
345     tr->Rollback();
346     strError = "IBPP exception";
347     printfd(__FILE__, ex.what());
348     return -1;
349     }
350
351 return 0;
352 }
353 //-----------------------------------------------------------------------------
354 int FIREBIRD_STORE::RestoreUserStat(USER_STAT * stat,
355                                     const std::string & login) const
356 {
357 STG_LOCKER lock(&mutex);
358
359 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
360 IBPP::Statement st = IBPP::StatementFactory(db, tr);
361
362 try
363     {
364     tr->Start();
365     st->Prepare("select pk_user from tb_users where name = ?");
366     st->Set(1, login);
367     st->Execute();
368     if (!st->Fetch())
369         {
370         strError = "User \"" + login + "\" not found in database";
371         printfd(__FILE__, "User '%s' not found in database\n", login.c_str());
372         return -1;
373         }
374     int32_t uid;
375     st->Get(1, uid);
376     st->Close();
377
378     st->Prepare("select first 1 pk_stat, cash, free_mb, last_activity_time, \
379                     last_cash_add, last_cash_add_time, passive_time from tb_stats \
380                  where fk_user = ? order by stats_date desc");
381     st->Set(1, uid);
382     st->Execute();
383     if (!st->Fetch())
384         {
385         strError = "No stat info for user \"" + login + "\"";
386         printfd(__FILE__, "No stat info for user '%s'\n", login.c_str());
387         tr->Rollback();
388         return -1;
389         }
390
391     int32_t sid;
392     st->Get(1, sid);
393     st->Get(2, stat->cash);
394     st->Get(3, stat->freeMb);
395     IBPP::Timestamp actTime;
396     st->Get(4, actTime);
397     st->Get(5, stat->lastCashAdd);
398     IBPP::Timestamp addTime;
399     st->Get(6, addTime);
400     int32_t passiveTime;
401     st->Get(7, passiveTime);
402
403     stat->passiveTime = passiveTime;
404
405     stat->lastActivityTime = ts2time_t(actTime);
406
407     stat->lastCashAddTime = ts2time_t(addTime);
408
409     st->Close();
410     st->Prepare("select * from tb_stats_traffic where fk_stat = ?");
411     st->Set(1, sid);
412     st->Execute();
413     for(int i = 0; i < DIR_NUM; i++)
414         {
415         if (st->Fetch())
416             {
417             int dir;
418             st->Get(3, dir);
419             st->Get(5, (int64_t &)stat->monthUp[dir]);
420             st->Get(4, (int64_t &)stat->monthDown[dir]);
421             }
422         else
423             {
424             break;
425             }
426         }
427     tr->Commit();
428     }
429
430 catch (IBPP::Exception & ex)
431     {
432     tr->Rollback();
433     strError = "IBPP exception";
434     printfd(__FILE__, ex.what());
435     return -1;
436     }
437
438 return 0;
439 }
440 //-----------------------------------------------------------------------------
441 int FIREBIRD_STORE::RestoreUserConf(USER_CONF * conf,
442                                     const std::string & login) const
443 {
444 STG_LOCKER lock(&mutex);
445
446 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
447 IBPP::Statement st = IBPP::StatementFactory(db, tr);
448
449 try
450     {
451     tr->Start();
452     st->Prepare("select tb_users.pk_user, tb_users.address, tb_users.always_online, \
453                         tb_users.credit, tb_users.credit_expire, tb_users.disabled, \
454                         tb_users.disabled_detail_stat, tb_users.email, tb_users.grp, \
455                         tb_users.note, tb_users.passive, tb_users.passwd, tb_users.phone, \
456                         tb_users.real_name, tf1.name, tf2.name, tb_corporations.name \
457                  from tb_users left join tb_tariffs tf1 \
458                  on tf1.pk_tariff = tb_users.fk_tariff \
459                  left join tb_tariffs tf2 \
460                  on tf2.pk_tariff = tb_users.fk_tariff_change \
461                  left join tb_corporations \
462                  on tb_corporations.pk_corporation = tb_users.fk_corporation \
463                  where tb_users.name = ?");
464     st->Set(1, login);
465     st->Execute();
466     if (!st->Fetch())
467         {
468         strError = "User \"" + login + "\" not found in database";
469     printfd(__FILE__, "User '%s' not found in database", login.c_str());
470         tr->Rollback();
471         return -1;
472         }
473     int32_t uid;
474     st->Get(1, uid);
475     // Getting base config
476     st->Get(2, conf->address);
477     bool test;
478     st->Get(3, test);
479     conf->alwaysOnline = test;
480     st->Get(4, conf->credit);
481     IBPP::Timestamp timestamp;
482     st->Get(5, timestamp);
483
484     conf->creditExpire = ts2time_t(timestamp);
485
486     st->Get(6, test);
487     conf->disabled = test;
488     st->Get(7, test);
489     conf->disabledDetailStat = test;
490     st->Get(8, conf->email);
491     st->Get(9, conf->group);
492     st->Get(10, conf->note);
493     st->Get(11, test);
494     conf->passive = test;
495     st->Get(12, conf->password);
496     st->Get(13, conf->phone);
497     st->Get(14, conf->realName);
498     st->Get(15, conf->tariffName);
499     st->Get(16, conf->nextTariff);
500     st->Get(17, conf->corp);
501
502     if (conf->tariffName == "")
503         conf->tariffName = NO_TARIFF_NAME;
504     if (conf->corp == "")
505         conf->corp = NO_CORP_NAME;
506
507     // Services
508     st->Close();
509     st->Prepare("select name from tb_services \
510                  where pk_service in \
511                     (select fk_service from tb_users_services \
512                      where fk_user = ?)");
513     st->Set(1, uid);
514     st->Execute();
515     while (st->Fetch())
516         {
517         std::string name;
518         st->Get(1, name);
519         conf->service.push_back(name);
520         }
521
522     // User data
523     st->Close();
524     st->Prepare("select data, num from tb_users_data where fk_user = ? order by num");
525     st->Set(1, uid);
526     st->Execute();
527     while (st->Fetch())
528         {
529         int i;
530         st->Get(2, i);
531         st->Get(1, conf->userdata[i]);
532         }
533
534     // User IPs
535     st->Close();
536     st->Prepare("select ip, mask from tb_allowed_ip \
537                  where fk_user = ?");
538     st->Set(1, uid);
539     st->Execute();
540     conf->ips.Erase();
541     while (st->Fetch())
542         {
543         IP_MASK im;
544         st->Get(1, (int32_t &)im.ip);
545         st->Get(2, (int32_t &)im.mask);
546         conf->ips.Add(im);
547         }
548
549     tr->Commit();
550     }
551 catch (IBPP::Exception & ex)
552     {
553     tr->Rollback();
554     strError = "IBPP exception";
555     printfd(__FILE__, ex.what());
556     return -1;
557     }
558
559 return 0;
560 }
561 //-----------------------------------------------------------------------------
562 int FIREBIRD_STORE::WriteUserChgLog(const std::string & login,
563                                     const std::string & admLogin,
564                                     uint32_t admIP,
565                                     const std::string & paramName,
566                                     const std::string & oldValue,
567                                     const std::string & newValue,
568                                     const std::string & message = "") const
569 {
570 STG_LOCKER lock(&mutex);
571
572 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
573 IBPP::Statement st = IBPP::StatementFactory(db, tr);
574 IBPP::Timestamp now;
575 now.Now();
576
577 std::string temp = ""; // Composed message for log
578
579 try
580     {
581     tr->Start();
582     temp += "Admin \"" + admLogin + "\", ";
583     temp += inet_ntostring(admIP);
584     temp += ": ";
585     temp = temp + message;
586     //----------------------------------------------------------------------------------------
587     // Checking and inserting parameters in params table
588     st->Prepare("select pk_parameter from tb_parameters where name = ?");
589     st->Set(1, paramName);
590     st->Execute();
591     if (!st->Fetch())
592         {
593         st->Close();
594         st->Prepare("insert into tb_parameters (name) values (?)");
595         st->Set(1, paramName);
596         st->Execute();
597         }
598     st->Close();
599     //----------------------------------------------------------------------------------------
600     st->Prepare("insert into tb_params_log \
601                     (fk_user, fk_parameter, event_time, from_val, to_val, comment) \
602                  values ((select pk_user from tb_users \
603                           where name = ?), \
604                          (select pk_parameter from tb_parameters \
605                           where name = ?), \
606                          ?, ?, ?, ?)");
607     st->Set(1, login);
608     st->Set(2, paramName);
609     st->Set(3, now);
610     st->Set(4, oldValue);
611     st->Set(5, newValue);
612     st->Set(6, temp);
613     st->Execute();
614     tr->Commit();
615     }
616
617 catch (IBPP::Exception & ex)
618     {
619     tr->Rollback();
620     strError = "IBPP exception";
621     printfd(__FILE__, ex.what());
622     return -1;
623     }
624
625 return 0;
626 }
627 //-----------------------------------------------------------------------------
628 int FIREBIRD_STORE::WriteUserConnect(const std::string & login, uint32_t ip) const
629 {
630 STG_LOCKER lock(&mutex);
631
632 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
633 IBPP::Statement st = IBPP::StatementFactory(db, tr);
634 IBPP::Timestamp now;
635 now.Now();
636
637 try
638     {
639     tr->Start();
640     st->Prepare("execute procedure sp_append_session_log(?, ?, 'c', ?)");
641     st->Set(1, login);
642     st->Set(2, now);
643     st->Set(3, (int32_t)ip);
644     tr->Commit();
645     }
646
647 catch (IBPP::Exception & ex)
648     {
649     tr->Rollback();
650     strError = "IBPP exception";
651     printfd(__FILE__, ex.what());
652     return -1;
653     }
654
655 return 0;
656 }
657 //-----------------------------------------------------------------------------
658 int FIREBIRD_STORE::WriteUserDisconnect(const std::string & login,
659                     const DIR_TRAFF & up,
660                     const DIR_TRAFF & down,
661                     const DIR_TRAFF & sessionUp,
662                     const DIR_TRAFF & sessionDown,
663                     double /*cash*/,
664                     double /*freeMb*/,
665                     const std::string & /*reason*/) const
666 {
667 STG_LOCKER lock(&mutex);
668
669 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
670 IBPP::Statement st = IBPP::StatementFactory(db, tr);
671 IBPP::Timestamp now;
672 now.Now();
673
674 try
675     {
676     tr->Start();
677     st->Prepare("execute procedure sp_append_session_log(?, ?, 'd', 0)");
678     st->Set(1, login);
679     st->Set(2, now);
680     st->Execute();
681     int32_t id;
682     st->Get(1, id);
683     st->Prepare("insert into tb_sessions_data \
684                     (fk_session_log, dir_num, session_upload, \
685                      session_download, month_upload, month_download) \
686                  values (?, ?, ?, ?, ?, ?)");
687     for(int i = 0; i < DIR_NUM; i++)
688         {
689         st->Set(1, id);
690         st->Set(2, i);
691         st->Set(3, (int64_t)sessionUp[i]);
692         st->Set(4, (int64_t)sessionDown[i]);
693         st->Set(5, (int64_t)up[i]);
694         st->Set(6, (int64_t)down[i]);
695         st->Execute();
696         }
697     tr->Commit();
698     }
699
700 catch (IBPP::Exception & ex)
701     {
702     tr->Rollback();
703     strError = "IBPP exception";
704     printfd(__FILE__, ex.what());
705     return -1;
706     }
707
708 return 0;
709 }
710 //-----------------------------------------------------------------------------
711 int FIREBIRD_STORE::WriteDetailedStat(const std::map<IP_DIR_PAIR, STAT_NODE> & statTree,
712                                       time_t lastStat,
713                                       const std::string & login) const
714 {
715 STG_LOCKER lock(&mutex);
716
717 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
718 IBPP::Statement st = IBPP::StatementFactory(db, tr);
719
720 IBPP::Timestamp statTime, now;
721 now.Now();
722
723 time_t2ts(lastStat, &statTime);
724
725 try
726     {
727     tr->Start();
728     std::map<IP_DIR_PAIR, STAT_NODE>::const_iterator it;
729     it = statTree.begin();
730     st->Prepare("insert into tb_detail_stats \
731                     (till_time, from_time, fk_user, dir_num, \
732                      ip, download, upload, cost) \
733                  values (?, ?, (select pk_user from tb_users \
734                                 where name = ?), \
735                      ?, ?, ?, ?, ?)");
736     while (it != statTree.end())
737         {
738         st->Set(1, now);
739         st->Set(2, statTime);
740         st->Set(3, login);
741         st->Set(4, it->first.dir);
742         st->Set(5, (int32_t)it->first.ip);
743         st->Set(6, (int64_t)it->second.down);
744         st->Set(7, (int64_t)it->second.up);
745         st->Set(8, it->second.cash);
746         st->Execute();
747         ++it;
748         }
749     tr->Commit();
750     }
751
752 catch (IBPP::Exception & ex)
753     {
754     tr->Rollback();
755     strError = "IBPP exception";
756     printfd(__FILE__, ex.what());
757     return -1;
758     }
759
760 return 0;
761 }
762 //-----------------------------------------------------------------------------
763 int FIREBIRD_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year, const std::string & login) const
764 {
765 STG_LOCKER lock(&mutex);
766
767 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
768 IBPP::Statement st = IBPP::StatementFactory(db, tr);
769
770 IBPP::Timestamp now;
771 IBPP::Date nowDate;
772 nowDate.Today();
773 now.Now();
774
775 if (SaveStat(stat, login, year, month))
776     {
777     return -1;
778     }
779
780 try
781     {
782     tr->Start();
783
784     st->Prepare("execute procedure sp_add_stat(?, 0, 0, ?, 0, ?, 0, ?)");
785     st->Set(1, login);
786     st->Set(2, now);
787     st->Set(3, now);
788     st->Set(4, nowDate);
789
790     st->Execute();
791     int32_t id;
792     st->Get(1, id);
793     st->Close();
794
795     st->Prepare("insert into tb_stats_traffic \
796                     (fk_stat, dir_num, upload, download) \
797                  values (?, ?, 0, 0)");
798
799     for(int i = 0; i < DIR_NUM; i++)
800         {
801         st->Set(1, id);
802         st->Set(2, i);
803         st->Execute();
804         }
805
806     tr->Commit();
807     }
808 catch (IBPP::Exception & ex)
809     {
810     tr->Rollback();
811     strError = "IBPP exception";
812     printfd(__FILE__, ex.what());
813     return -1;
814     }
815
816 return 0;
817 }
818 //-----------------------------------------------------------------------------
819