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