]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/store/firebird/firebird_store_users.cpp
Added migration scripts for new daily fee algo.
[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(vector<string> * usersList) const
35 {
36 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
37
38 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
39 IBPP::Statement st = IBPP::StatementFactory(db, tr);
40
41 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 string & name) const
67 {
68 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
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 string & login) const
95 {
96 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
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 string & login) const
123 {
124 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
125
126 return SaveStat(stat, login);
127 }
128 //-----------------------------------------------------------------------------
129 int FIREBIRD_STORE::SaveStat(const USER_STAT & stat,
130                                  const string & login,
131                                  int year,
132                                  int month) const
133 {
134
135 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
136 IBPP::Statement st = IBPP::StatementFactory(db, tr);
137
138 IBPP::Timestamp actTime;
139 IBPP::Timestamp addTime;
140 IBPP::Date dt;
141 int i;
142 int32_t sid, uid;
143
144 try
145     {
146     tr->Start();
147     st->Prepare("select pk_user from tb_users where name = ?");
148     st->Set(1, login);
149     st->Execute();
150     if (!st->Fetch())
151     {
152     strError = "User \"" + login + "\" not found in database";
153     printfd(__FILE__, "User '%s' not found in database\n", login.c_str());
154     tr->Rollback();
155     return -1;
156     }
157     st->Get(1, uid);
158     st->Close();
159     st->Prepare("select first 1 pk_stat from tb_stats where fk_user = ? order by stats_date desc");
160     st->Set(1, uid);
161     st->Execute();
162     if (!st->Fetch())
163     {
164     tr->Rollback();
165     strError = "No stat info for user \"" + login + "\"";
166     printfd(__FILE__, "No stat info for user '%s'\n", login.c_str());
167     return -1;
168     }
169     st->Get(1, sid);
170     st->Close();
171
172     time_t2ts(stat.lastActivityTime, &actTime);
173     time_t2ts(stat.lastCashAddTime, &addTime);
174     if (year != 0)
175         ym2date(year, month, &dt);
176     else
177         dt.Today();
178
179     st->Prepare("update tb_stats set \
180                     cash = ?, \
181                     free_mb = ?, \
182                     last_activity_time = ?, \
183                     last_cash_add = ?, \
184                     last_cash_add_time = ?, \
185                     passive_time = ?, \
186                     stats_date = ? \
187                  where pk_stat = ?");
188
189     st->Set(1, stat.cash);
190     st->Set(2, stat.freeMb);
191     st->Set(3, actTime);
192     st->Set(4, stat.lastCashAdd);
193     st->Set(5, addTime);
194     st->Set(6, (int32_t)stat.passiveTime);
195     st->Set(7, dt);
196     st->Set(8, sid);
197
198     st->Execute();
199     st->Close();
200
201     for(i = 0; i < DIR_NUM; i++)
202         {
203         st->Prepare("update tb_stats_traffic set \
204                         upload = ?, \
205                         download = ? \
206                      where fk_stat = ? and dir_num = ?");
207         st->Set(1, (int64_t)stat.up[i]);
208         st->Set(2, (int64_t)stat.down[i]);
209         st->Set(3, sid);
210         st->Set(4, i);
211         st->Execute();
212         st->Close();
213         }
214
215     tr->Commit();
216     }
217
218 catch (IBPP::Exception & ex)
219     {
220     tr->Rollback();
221     strError = "IBPP exception";
222     printfd(__FILE__, ex.what());
223     return -1;
224     }
225
226 return 0;
227 }
228 //-----------------------------------------------------------------------------
229 int FIREBIRD_STORE::SaveUserConf(const USER_CONF & conf,
230                                  const string & login) const
231 {
232 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
233
234 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
235 IBPP::Statement st = IBPP::StatementFactory(db, tr);
236
237 int i;
238 int32_t uid;
239 IBPP::Timestamp creditExpire;
240 vector<string>::const_iterator it;
241
242 try
243     {
244     tr->Start();
245     st->Prepare("select pk_user from tb_users where name = ?");
246     st->Set(1, login);
247     st->Execute();
248     if (!st->Fetch())
249         {
250         strError = "User \"" + login + "\" not found in database";
251         printfd(__FILE__, "User '%s' not found in database\n", login.c_str());
252         tr->Rollback();
253         return -1;
254         }
255     st->Get(1, uid);
256     st->Close();
257
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(it = conf.service.begin(); it != conf.service.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     i = 0;
325     st->Prepare("insert into tb_users_data (fk_user, data, num) values (?, ?, ?)");
326     for (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(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
350 catch (IBPP::Exception & ex)
351     {
352     tr->Rollback();
353     strError = "IBPP exception";
354     printfd(__FILE__, ex.what());
355     return -1;
356     }
357
358 return 0;
359 }
360 //-----------------------------------------------------------------------------
361 int FIREBIRD_STORE::RestoreUserStat(USER_STAT * stat,
362                                     const string & login) const
363 {
364 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
365
366 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
367 IBPP::Statement st = IBPP::StatementFactory(db, tr);
368
369 IBPP::Timestamp actTime, addTime;
370 int i, dir;
371 int32_t uid, sid, passiveTime;
372
373 try
374     {
375     tr->Start();
376     st->Prepare("select pk_user from tb_users where name = ?");
377     st->Set(1, login);
378     st->Execute();
379     if (!st->Fetch())
380         {
381         strError = "User \"" + login + "\" not found in database";
382         printfd(__FILE__, "User '%s' not found in database\n", login.c_str());
383         return -1;
384         }
385     st->Get(1, uid);
386     st->Close();
387
388     st->Prepare("select first 1 pk_stat, cash, free_mb, last_activity_time, \
389                     last_cash_add, last_cash_add_time, passive_time from tb_stats \
390                  where fk_user = ? order by stats_date desc");
391     st->Set(1, uid);
392     st->Execute();
393     if (!st->Fetch())
394         {
395         strError = "No stat info for user \"" + login + "\"";
396         printfd(__FILE__, "No stat info for user '%s'\n", login.c_str());
397         tr->Rollback();
398         return -1;
399         }
400
401     st->Get(1, sid);
402     st->Get(2, stat->cash);
403     st->Get(3, stat->freeMb);
404     st->Get(4, actTime);
405     st->Get(5, stat->lastCashAdd);
406     st->Get(6, addTime);
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(i = 0; i < DIR_NUM; i++)
420         {
421         if (st->Fetch())
422             {
423             st->Get(3, dir);
424             st->Get(5, (int64_t &)stat->up[dir]);
425             st->Get(4, (int64_t &)stat->down[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(USER_CONF * conf,
447                                     const string & login) const
448 {
449 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
450
451 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
452 IBPP::Statement st = IBPP::StatementFactory(db, tr);
453
454 int32_t uid;
455 int i;
456 IBPP::Timestamp timestamp;
457 IP_MASK im;
458 string name;
459 bool test;
460
461 try
462     {
463     tr->Start();
464     st->Prepare("select tb_users.pk_user, tb_users.address, tb_users.always_online, \
465                         tb_users.credit, tb_users.credit_expire, tb_users.disabled, \
466                         tb_users.disabled_detail_stat, tb_users.email, tb_users.grp, \
467                         tb_users.note, tb_users.passive, tb_users.passwd, tb_users.phone, \
468                         tb_users.real_name, tf1.name, tf2.name, tb_corporations.name \
469                  from tb_users left join tb_tariffs tf1 \
470                  on tf1.pk_tariff = tb_users.fk_tariff \
471                  left join tb_tariffs tf2 \
472                  on tf2.pk_tariff = tb_users.fk_tariff_change \
473                  left join tb_corporations \
474                  on tb_corporations.pk_corporation = tb_users.fk_corporation \
475                  where tb_users.name = ?");
476     st->Set(1, login);
477     st->Execute();
478     if (!st->Fetch())
479         {
480         strError = "User \"" + login + "\" not found in database";
481     printfd(__FILE__, "User '%s' not found in database", login.c_str());
482         tr->Rollback();
483         return -1;
484         }
485     st->Get(1, uid);
486     // Getting base config
487     st->Get(2, conf->address);
488     st->Get(3, test);
489     conf->alwaysOnline = test;
490     st->Get(4, conf->credit);
491     st->Get(5, timestamp);
492
493     conf->creditExpire = ts2time_t(timestamp);
494
495     st->Get(6, test);
496     conf->disabled = test;
497     st->Get(7, test);
498     conf->disabledDetailStat = test;
499     st->Get(8, conf->email);
500     st->Get(9, conf->group);
501     st->Get(10, conf->note);
502     st->Get(11, test);
503     conf->passive = test;
504     st->Get(12, conf->password);
505     st->Get(13, conf->phone);
506     st->Get(14, conf->realName);
507     st->Get(15, conf->tariffName);
508     st->Get(16, conf->nextTariff);
509     st->Get(17, conf->corp);
510
511     if (conf->tariffName == "")
512         conf->tariffName = NO_TARIFF_NAME;
513     if (conf->corp == "")
514         conf->corp = NO_CORP_NAME;
515
516     // Services
517     st->Close();
518     st->Prepare("select name from tb_services \
519                  where pk_service in \
520                     (select fk_service from tb_users_services \
521                      where fk_user = ?)");
522     st->Set(1, uid);
523     st->Execute();
524     while (st->Fetch())
525         {
526         st->Get(1, name);
527         conf->service.push_back(name);
528         }
529
530     // User data
531     st->Close();
532     st->Prepare("select data, num from tb_users_data where fk_user = ? order by num");
533     st->Set(1, uid);
534     st->Execute();
535     while (st->Fetch())
536         {
537         st->Get(2, i);
538         st->Get(1, conf->userdata[i]);
539         }
540
541     // User IPs
542     st->Close();
543     st->Prepare("select ip, mask from tb_allowed_ip \
544                  where fk_user = ?");
545     st->Set(1, uid);
546     st->Execute();
547     conf->ips.Erase();
548     while (st->Fetch())
549         {
550         st->Get(1, (int32_t &)im.ip);
551         st->Get(2, (int32_t &)im.mask);
552         conf->ips.Add(im);
553         }
554
555     tr->Commit();
556     }
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 string & login,
570                                     const string & admLogin,
571                                     uint32_t admIP,
572                                     const string & paramName,
573                                     const string & oldValue,
574                                     const string & newValue,
575                                     const string & message = "") const
576 {
577 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
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 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 string & login, uint32_t ip) const
636 {
637 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
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 string & login,
666                     const DIR_TRAFF & up,
667                     const DIR_TRAFF & down,
668                     const DIR_TRAFF & sessionUp,
669                     const DIR_TRAFF & sessionDown,
670                     double cash,
671                     double freeMb,
672                     const std::string & reason) const
673 {
674 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
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 int32_t id;
682 int i;
683
684 try
685     {
686     tr->Start();
687     st->Prepare("execute procedure sp_append_session_log(?, ?, 'd', 0)");
688     st->Set(1, login);
689     st->Set(2, now);
690     st->Execute();
691     st->Get(1, id);
692     st->Prepare("insert into tb_sessions_data \
693                     (fk_session_log, dir_num, session_upload, \
694                      session_download, month_upload, month_download) \
695                  values (?, ?, ?, ?, ?, ?)");
696     for(i = 0; i < DIR_NUM; i++)
697         {
698         st->Set(1, id);
699         st->Set(2, i);
700         st->Set(3, (int64_t)sessionUp[i]);
701         st->Set(4, (int64_t)sessionDown[i]);
702         st->Set(5, (int64_t)up[i]);
703         st->Set(6, (int64_t)down[i]);
704         st->Execute();
705         }
706     tr->Commit();
707     }
708
709 catch (IBPP::Exception & ex)
710     {
711     tr->Rollback();
712     strError = "IBPP exception";
713     printfd(__FILE__, ex.what());
714     return -1;
715     }
716
717 return 0;
718 }
719 //-----------------------------------------------------------------------------
720 int FIREBIRD_STORE::WriteDetailedStat(const map<IP_DIR_PAIR, STAT_NODE> & statTree,
721                                       time_t lastStat,
722                                       const string & login) const
723 {
724 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
725
726 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
727 IBPP::Statement st = IBPP::StatementFactory(db, tr);
728
729 IBPP::Timestamp statTime, now;
730 now.Now();
731
732 time_t2ts(lastStat, &statTime);
733
734 try
735     {
736     tr->Start();
737     map<IP_DIR_PAIR, STAT_NODE>::const_iterator it;
738     it = statTree.begin();
739     st->Prepare("insert into tb_detail_stats \
740                     (till_time, from_time, fk_user, dir_num, \
741                      ip, download, upload, cost) \
742                  values (?, ?, (select pk_user from tb_users \
743                                 where name = ?), \
744                      ?, ?, ?, ?, ?)");
745     while (it != statTree.end())
746         {
747         st->Set(1, now);
748         st->Set(2, statTime);
749         st->Set(3, login);
750         st->Set(4, it->first.dir);
751         st->Set(5, (int32_t)it->first.ip);
752         st->Set(6, (int64_t)it->second.down);
753         st->Set(7, (int64_t)it->second.up);
754         st->Set(8, it->second.cash);
755         st->Execute();
756         ++it;
757         }
758     tr->Commit();
759     }
760
761 catch (IBPP::Exception & ex)
762     {
763     tr->Rollback();
764     strError = "IBPP exception";
765     printfd(__FILE__, ex.what());
766     return -1;
767     }
768
769 return 0;
770 }
771 //-----------------------------------------------------------------------------
772 int FIREBIRD_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year, const string & login) const
773 {
774 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
775
776 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
777 IBPP::Statement st = IBPP::StatementFactory(db, tr);
778
779 IBPP::Timestamp now;
780 IBPP::Date nowDate;
781 nowDate.Today();
782 now.Now();
783 int32_t id;
784 int i;
785
786 if (SaveStat(stat, login, year, month))
787     {
788     return -1;
789     }
790
791 try
792     {
793     tr->Start();
794
795     st->Prepare("execute procedure sp_add_stat(?, 0, 0, ?, 0, ?, 0, ?)");
796     st->Set(1, login);
797     st->Set(2, now);
798     st->Set(3, now);
799     st->Set(4, nowDate);
800
801     st->Execute();
802     st->Get(1, id);
803     st->Close();
804
805     st->Prepare("insert into tb_stats_traffic \
806                     (fk_stat, dir_num, upload, download) \
807                  values (?, ?, 0, 0)");
808
809     for(i = 0; i < DIR_NUM; i++)
810         {
811         st->Set(1, id);
812         st->Set(2, i);
813         st->Execute();
814         }
815
816     tr->Commit();
817     }
818
819 catch (IBPP::Exception & ex)
820     {
821     tr->Rollback();
822     strError = "IBPP exception";
823     printfd(__FILE__, ex.what());
824     return -1;
825     }
826
827 return 0;
828 }
829 //-----------------------------------------------------------------------------
830