]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/store/firebird/firebird_store_users.cpp
Merge branch 'stg-2.409' into stg-2.409-radius
[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     USER_IPS ips;
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         ips.Add(im);
547         }
548     conf->ips = ips;
549
550     tr->Commit();
551     }
552 catch (IBPP::Exception & ex)
553     {
554     tr->Rollback();
555     strError = "IBPP exception";
556     printfd(__FILE__, ex.what());
557     return -1;
558     }
559
560 return 0;
561 }
562 //-----------------------------------------------------------------------------
563 int FIREBIRD_STORE::WriteUserChgLog(const std::string & login,
564                                     const std::string & admLogin,
565                                     uint32_t admIP,
566                                     const std::string & paramName,
567                                     const std::string & oldValue,
568                                     const std::string & newValue,
569                                     const std::string & message = "") const
570 {
571 STG_LOCKER lock(&mutex);
572
573 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
574 IBPP::Statement st = IBPP::StatementFactory(db, tr);
575 IBPP::Timestamp now;
576 now.Now();
577
578 std::string temp = ""; // Composed message for log
579
580 try
581     {
582     tr->Start();
583     temp += "Admin \"" + admLogin + "\", ";
584     temp += inet_ntostring(admIP);
585     temp += ": ";
586     temp = temp + message;
587     //----------------------------------------------------------------------------------------
588     // Checking and inserting parameters in params table
589     st->Prepare("select pk_parameter from tb_parameters where name = ?");
590     st->Set(1, paramName);
591     st->Execute();
592     if (!st->Fetch())
593         {
594         st->Close();
595         st->Prepare("insert into tb_parameters (name) values (?)");
596         st->Set(1, paramName);
597         st->Execute();
598         }
599     st->Close();
600     //----------------------------------------------------------------------------------------
601     st->Prepare("insert into tb_params_log \
602                     (fk_user, fk_parameter, event_time, from_val, to_val, comment) \
603                  values ((select pk_user from tb_users \
604                           where name = ?), \
605                          (select pk_parameter from tb_parameters \
606                           where name = ?), \
607                          ?, ?, ?, ?)");
608     st->Set(1, login);
609     st->Set(2, paramName);
610     st->Set(3, now);
611     st->Set(4, oldValue);
612     st->Set(5, newValue);
613     st->Set(6, temp);
614     st->Execute();
615     tr->Commit();
616     }
617
618 catch (IBPP::Exception & ex)
619     {
620     tr->Rollback();
621     strError = "IBPP exception";
622     printfd(__FILE__, ex.what());
623     return -1;
624     }
625
626 return 0;
627 }
628 //-----------------------------------------------------------------------------
629 int FIREBIRD_STORE::WriteUserConnect(const std::string & login, uint32_t ip) const
630 {
631 STG_LOCKER lock(&mutex);
632
633 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
634 IBPP::Statement st = IBPP::StatementFactory(db, tr);
635 IBPP::Timestamp now;
636 now.Now();
637
638 try
639     {
640     tr->Start();
641     st->Prepare("execute procedure sp_append_session_log(?, ?, 'c', ?)");
642     st->Set(1, login);
643     st->Set(2, now);
644     st->Set(3, (int32_t)ip);
645     tr->Commit();
646     }
647
648 catch (IBPP::Exception & ex)
649     {
650     tr->Rollback();
651     strError = "IBPP exception";
652     printfd(__FILE__, ex.what());
653     return -1;
654     }
655
656 return 0;
657 }
658 //-----------------------------------------------------------------------------
659 int FIREBIRD_STORE::WriteUserDisconnect(const std::string & login,
660                     const DIR_TRAFF & up,
661                     const DIR_TRAFF & down,
662                     const DIR_TRAFF & sessionUp,
663                     const DIR_TRAFF & sessionDown,
664                     double /*cash*/,
665                     double /*freeMb*/,
666                     const std::string & /*reason*/) const
667 {
668 STG_LOCKER lock(&mutex);
669
670 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
671 IBPP::Statement st = IBPP::StatementFactory(db, tr);
672 IBPP::Timestamp now;
673 now.Now();
674
675 try
676     {
677     tr->Start();
678     st->Prepare("execute procedure sp_append_session_log(?, ?, 'd', 0)");
679     st->Set(1, login);
680     st->Set(2, now);
681     st->Execute();
682     int32_t id;
683     st->Get(1, id);
684     st->Prepare("insert into tb_sessions_data \
685                     (fk_session_log, dir_num, session_upload, \
686                      session_download, month_upload, month_download) \
687                  values (?, ?, ?, ?, ?, ?)");
688     for(int i = 0; i < DIR_NUM; i++)
689         {
690         st->Set(1, id);
691         st->Set(2, i);
692         st->Set(3, (int64_t)sessionUp[i]);
693         st->Set(4, (int64_t)sessionDown[i]);
694         st->Set(5, (int64_t)up[i]);
695         st->Set(6, (int64_t)down[i]);
696         st->Execute();
697         }
698     tr->Commit();
699     }
700
701 catch (IBPP::Exception & ex)
702     {
703     tr->Rollback();
704     strError = "IBPP exception";
705     printfd(__FILE__, ex.what());
706     return -1;
707     }
708
709 return 0;
710 }
711 //-----------------------------------------------------------------------------
712 int FIREBIRD_STORE::WriteDetailedStat(const std::map<IP_DIR_PAIR, STAT_NODE> & statTree,
713                                       time_t lastStat,
714                                       const std::string & login) const
715 {
716 STG_LOCKER lock(&mutex);
717
718 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
719 IBPP::Statement st = IBPP::StatementFactory(db, tr);
720
721 IBPP::Timestamp statTime, now;
722 now.Now();
723
724 time_t2ts(lastStat, &statTime);
725
726 try
727     {
728     tr->Start();
729     std::map<IP_DIR_PAIR, STAT_NODE>::const_iterator it;
730     it = statTree.begin();
731     st->Prepare("insert into tb_detail_stats \
732                     (till_time, from_time, fk_user, dir_num, \
733                      ip, download, upload, cost) \
734                  values (?, ?, (select pk_user from tb_users \
735                                 where name = ?), \
736                      ?, ?, ?, ?, ?)");
737     while (it != statTree.end())
738         {
739         st->Set(1, now);
740         st->Set(2, statTime);
741         st->Set(3, login);
742         st->Set(4, it->first.dir);
743         st->Set(5, (int32_t)it->first.ip);
744         st->Set(6, (int64_t)it->second.down);
745         st->Set(7, (int64_t)it->second.up);
746         st->Set(8, it->second.cash);
747         st->Execute();
748         ++it;
749         }
750     tr->Commit();
751     }
752
753 catch (IBPP::Exception & ex)
754     {
755     tr->Rollback();
756     strError = "IBPP exception";
757     printfd(__FILE__, ex.what());
758     return -1;
759     }
760
761 return 0;
762 }
763 //-----------------------------------------------------------------------------
764 int FIREBIRD_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year, const std::string & login) const
765 {
766 STG_LOCKER lock(&mutex);
767
768 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
769 IBPP::Statement st = IBPP::StatementFactory(db, tr);
770
771 IBPP::Timestamp now;
772 IBPP::Date nowDate;
773 nowDate.Today();
774 now.Now();
775
776 if (SaveStat(stat, login, year, month))
777     {
778     return -1;
779     }
780
781 try
782     {
783     tr->Start();
784
785     st->Prepare("execute procedure sp_add_stat(?, 0, 0, ?, 0, ?, 0, ?)");
786     st->Set(1, login);
787     st->Set(2, now);
788     st->Set(3, now);
789     st->Set(4, nowDate);
790
791     st->Execute();
792     int32_t id;
793     st->Get(1, id);
794     st->Close();
795
796     st->Prepare("insert into tb_stats_traffic \
797                     (fk_stat, dir_num, upload, download) \
798                  values (?, ?, 0, 0)");
799
800     for(int i = 0; i < DIR_NUM; i++)
801         {
802         st->Set(1, id);
803         st->Set(2, i);
804         st->Execute();
805         }
806
807     tr->Commit();
808     }
809 catch (IBPP::Exception & ex)
810     {
811     tr->Rollback();
812     strError = "IBPP exception";
813     printfd(__FILE__, ex.what());
814     return -1;
815     }
816
817 return 0;
818 }
819 //-----------------------------------------------------------------------------
820