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