]> git.stg.codes - stg.git/commitdiff
Merge branch 'master' into full-month-stats
authorMaxim Mamontov <faust.madf@gmail.com>
Fri, 26 Jul 2013 18:53:47 +0000 (21:53 +0300)
committerMaxim Mamontov <faust.madf@gmail.com>
Fri, 26 Jul 2013 18:53:47 +0000 (21:53 +0300)
Conflicts:
projects/stargazer/plugins/store/postgresql/postgresql_store_users.cpp

1  2 
projects/stargazer/plugins/store/postgresql/postgresql_store.h
projects/stargazer/plugins/store/postgresql/postgresql_store_users.cpp

index 654de1467674cb79c352e0b2901d094a33d3b31e,72a2c22c01c951fbd7bed410f12189036456776b..4585bbdf30146adba3247cc778f6c7a375d44501
  
  #include <string>
  #include <vector>
- #include <map>
  
  #include "stg/store.h"
  #include "stg/logger.h"
  
 -// Minimal DB version is 5
 -// Recommended DB version is 6 (support FreeMb logging on disconnects)
 -#define DB_MIN_VERSION 5
 +// Minimal DB version is 7
 +// Recommended DB version is 7 (support full month stats)
 +#define DB_MIN_VERSION 7
  
- extern "C" STORE * GetStore();
  class POSTGRESQL_STORE : public STORE {
  public:
      POSTGRESQL_STORE();
@@@ -97,7 -94,7 +94,7 @@@
      // Tariffs
      int GetTariffsList(std::vector<std::string> * tariffsList) const;
      int AddTariff(const std::string & name) const;
-     int DelTariff(const string & name) const;
+     int DelTariff(const std::string & name) const;
      int SaveTariff(const TARIFF_DATA & td, const std::string & tariffName) const;
      int RestoreTariff(TARIFF_DATA * td, const std::string & tariffName) const;
  
      int DelService(const std::string & name) const;
  
      // Settings
-     inline void SetSettings(const MODULE_SETTINGS & s) { settings = s; };
+     inline void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
      int ParseSettings();
  
-     inline const string & GetStrError() const { return strError; };
-     inline const string & GetVersion() const { return versionString; };
+     inline const std::string & GetStrError() const { return strError; }
+     inline const std::string & GetVersion() const { return versionString; }
  private:
      POSTGRESQL_STORE(const POSTGRESQL_STORE & rvalue);
      POSTGRESQL_STORE & operator=(const POSTGRESQL_STORE & rvalue);
  
      int EscapeString(std::string & value) const;
  
-     std::string Int2TS(uint32_t value) const;
-     uint32_t TS2Int(const std::string & value) const;
+     std::string Int2TS(time_t value) const;
+     time_t TS2Int(const std::string & value) const;
  
      int SaveStat(const USER_STAT & stat, const std::string & login, int year = 0, int month = 0) const;
  
      PLUGIN_LOGGER logger;
  };
  
- extern const volatile time_t stgTime;
  #endif //POSTGRESQL_STORE_H
index df802eea9f00bae0657daab3d93c61e7485923c5,0722cc4c8d76671982b60fcf2dd948a7ba8d7746..f8eba5c12a8d957e002ef17ca1b0ac8c2f205b77
@@@ -39,7 -39,7 +39,7 @@@
  #include "postgresql_store.h"
  
  //-----------------------------------------------------------------------------
- int POSTGRESQL_STORE::GetUsersList(vector<string> * usersList) const
+ int POSTGRESQL_STORE::GetUsersList(std::vector<std::string> * usersList) const
  {
  STG_LOCKER lock(&mutex, __FILE__, __LINE__);
  
@@@ -95,7 -95,7 +95,7 @@@ return 0
  }
  
  //-----------------------------------------------------------------------------
- int POSTGRESQL_STORE::AddUser(const string & name) const
+ int POSTGRESQL_STORE::AddUser(const std::string & name) const
  {
  STG_LOCKER lock(&mutex, __FILE__, __LINE__);
  
@@@ -130,7 -130,7 +130,7 @@@ if (EscapeString(elogin)
      return -1;
      }
  
- std::stringstream query;
+ std::ostringstream query;
  query << "SELECT sp_add_user('" << elogin << "')";
  
  result = PQexec(connection, query.str().c_str());
@@@ -159,7 -159,7 +159,7 @@@ return 0
  }
  
  //-----------------------------------------------------------------------------
- int POSTGRESQL_STORE::DelUser(const string & login) const
+ int POSTGRESQL_STORE::DelUser(const std::string & login) const
  {
  STG_LOCKER lock(&mutex, __FILE__, __LINE__);
  
@@@ -194,7 -194,7 +194,7 @@@ if (EscapeString(elogin)
      return -1;
      }
  
- std::stringstream query;
+ std::ostringstream query;
  query << "DELETE FROM tb_users WHERE name = '" << elogin << "'";
  
  result = PQexec(connection, query.str().c_str());
@@@ -223,24 -223,34 +223,24 @@@ return 0
  }
  //-----------------------------------------------------------------------------
  int POSTGRESQL_STORE::SaveUserStat(const USER_STAT & stat,
-                                    const string & login) const
+                                    const std::string & login) const
  {
  STG_LOCKER lock(&mutex, __FILE__, __LINE__);
  
 -return SaveStat(stat, login);
 -}
 -//-----------------------------------------------------------------------------
 -int POSTGRESQL_STORE::SaveStat(const USER_STAT & stat,
 -                               const std::string & login,
 -                               int year,
 -                               int month) const
 -{
  if (PQstatus(connection) != CONNECTION_OK)
      {
 -    printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
 +    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserStat(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
      if (Reset())
          {
          strError = "Connection lost";
 -        printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): '%s'\n", strError.c_str());
 +        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserStat(): '%s'\n", strError.c_str());
          return -1;
          }
      }
  
 -PGresult * result;
 -
  if (StartTransaction())
      {
 -    printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to start transaction'\n");
 +    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserStat(): 'Failed to start transaction'\n");
      return -1;
      }
  
@@@ -248,15 -258,15 +248,15 @@@ std::string elogin = login
  
  if (EscapeString(elogin))
      {
 -    printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to escape login'\n");
 +    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserStat(): 'Failed to escape login'\n");
      if (RollbackTransaction())
        {
 -      printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to rollback transaction'\n");
 +      printfd(__FILE__, "POSTGRESQL_STORE::SaveUserStat(): 'Failed to rollback transaction'\n");
        }
      return -1;
      }
  
- std::stringstream query;
+ std::ostringstream query;
  query << "UPDATE tb_users SET "
              "cash = " << stat.cash << ", "
              "free_mb = " << stat.freeMb << ", "
              "passive_time = " << stat.passiveTime << " "
           "WHERE name = '" << elogin << "'";
  
 -result = PQexec(connection, query.str().c_str());
 +PGresult * result = PQexec(connection, query.str().c_str());
  
  if (PQresultStatus(result) != PGRES_COMMAND_OK)
      {
      strError = PQresultErrorMessage(result);
      PQclear(result);
 -    printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): '%s'\n", strError.c_str());
 +    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserStat(): '%s'\n", strError.c_str());
      if (RollbackTransaction())
        {
 -      printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to rollback transaction'\n");
 +      printfd(__FILE__, "POSTGRESQL_STORE::SaveUserStat(): 'Failed to rollback transaction'\n");
        }
      return -1;
      }
  
  PQclear(result);
  
 -std::string date;
 -
 -MakeDate(date, year, month);
 -
  for (int dir = 0; dir < DIR_NUM; ++dir)
      {
      query.str("");
      query << "SELECT sp_add_stats_traffic ("
                  "'" << elogin << "', "
 -                "CAST('" << date << "' AS DATE), "
                  "CAST(" << dir << " AS SMALLINT), "
                  "CAST(" << stat.up[dir] << " AS BIGINT), "
                  "CAST(" << stat.down[dir] << " AS BIGINT))";
          {
          strError = PQresultErrorMessage(result);
          PQclear(result);
 -        printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): '%s'\n", strError.c_str());
 +        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserStat(): '%s'\n", strError.c_str());
          if (RollbackTransaction())
              {
 -            printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to rollback transaction'\n");
 +            printfd(__FILE__, "POSTGRESQL_STORE::SaveUserStat(): 'Failed to rollback transaction'\n");
              }
          return -1;
          }
  
  if (CommitTransaction())
      {
 -    printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to commit transaction'\n");
 +    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserStat(): 'Failed to commit transaction'\n");
      return -1;
      }
  
@@@ -319,7 -334,7 +319,7 @@@ return 0
  
  //-----------------------------------------------------------------------------
  int POSTGRESQL_STORE::SaveUserConf(const USER_CONF & conf,
-                                  const string & login) const
+                                  const std::string & login) const
  {
  STG_LOCKER lock(&mutex, __FILE__, __LINE__);
  
@@@ -354,7 -369,7 +354,7 @@@ if (EscapeString(elogin)
      return -1;
      }
  
- std::stringstream query;
+ std::ostringstream query;
  query << "SELECT pk_user FROM tb_users WHERE name = '" << elogin << "'";
  
  result = PQexec(connection, query.str().c_str());
@@@ -385,14 -400,16 +385,16 @@@ if (tuples != 1
      return -1;
      }
  
- std::stringstream tuple;
- tuple << PQgetvalue(result, 0, 0);
+ uint32_t uid;
  
- PQclear(result);
+     {
+     std::stringstream tuple;
+     tuple << PQgetvalue(result, 0, 0);
  
uint32_t uid;
    PQclear(result);
  
- tuple >> uid;
+     tuple >> uid;
+     }
  
  std::string eaddress = conf.address;
  std::string eemail = conf.email;
@@@ -588,7 -605,7 +590,7 @@@ return 0
  
  //-----------------------------------------------------------------------------
  int POSTGRESQL_STORE::RestoreUserStat(USER_STAT * stat,
-                                     const string & login) const
+                                     const std::string & login) const
  {
  STG_LOCKER lock(&mutex, __FILE__, __LINE__);
  
@@@ -623,14 -640,16 +625,16 @@@ if (EscapeString(elogin)
      return -1;
      }
  
- std::stringstream query;
- query << "SELECT pk_user, cash, free_mb, "
-             "last_activity_time, last_cash_add, "
-             "last_cash_add_time, passive_time "
-          "FROM tb_users "
-          "WHERE name = '" << elogin << "'";
+     {
+     std::ostringstream query;
 -    query << "SELECT cash, free_mb, "
++    query << "SELECT pk_user, cash, free_mb, "
+                 "last_activity_time, last_cash_add, "
+                 "last_cash_add_time, passive_time "
+              "FROM tb_users "
+              "WHERE name = '" << elogin << "'";
  
- result = PQexec(connection, query.str().c_str());
+     result = PQexec(connection, query.str().c_str());
+     }
  
  if (PQresultStatus(result) != PGRES_TUPLES_OK)
      {
@@@ -658,32 -677,32 +662,35 @@@ if (tuples != 1
      return -1;
      }
  
- std::stringstream tuple;
- tuple << PQgetvalue(result, 0, 0) << " ";
- tuple << PQgetvalue(result, 0, 1) << " ";
- tuple << PQgetvalue(result, 0, 2) << " ";
- stat->lastActivityTime = TS2Int(PQgetvalue(result, 0, 3));
- tuple << PQgetvalue(result, 0, 4) << " ";
- stat->lastCashAddTime = TS2Int(PQgetvalue(result, 0, 5));
- tuple << PQgetvalue(result, 0, 6);
- PQclear(result);
 +uint32_t uid;
 +
- tuple >> uid
-       >> stat->cash
-       >> stat->freeMb
-       >> stat->lastCashAdd
-       >> stat->passiveTime;
+     {
+     std::stringstream tuple;
+     tuple << PQgetvalue(result, 0, 0) << " ";
+     tuple << PQgetvalue(result, 0, 1) << " ";
 -    stat->lastActivityTime = TS2Int(PQgetvalue(result, 0, 2));
 -    tuple << PQgetvalue(result, 0, 3) << " ";
 -    stat->lastCashAddTime = TS2Int(PQgetvalue(result, 0, 4));
 -    tuple << PQgetvalue(result, 0, 5) << " ";
++    tuple << PQgetvalue(result, 0, 2) << " ";
++    stat->lastActivityTime = TS2Int(PQgetvalue(result, 0, 3));
++    tuple << PQgetvalue(result, 0, 4) << " ";
++    stat->lastCashAddTime = TS2Int(PQgetvalue(result, 0, 5));
++    tuple << PQgetvalue(result, 0, 6) << " ";
  
query.str("");
    PQclear(result);
  
- query << "SELECT dir_num, upload, download "
-          "FROM tb_stats_traffic "
-          "WHERE fk_user = " << uid;
 -    tuple >> stat->cash
++    tuple >> uid
++          >> stat->cash
+           >> stat->freeMb
+           >> stat->lastCashAdd
+           >> stat->passiveTime;
+     }
  
- result = PQexec(connection, query.str().c_str());
+     {
+     std::ostringstream query;
+     query << "SELECT dir_num, upload, download "
+              "FROM tb_stats_traffic "
 -             "WHERE fk_user IN (SELECT pk_user FROM tb_users WHERE name = '" << elogin << "') AND "
 -                   "DATE_TRUNC('month', stats_date) = DATE_TRUNC('month', CAST('" << Int2TS(stgTime) << "' AS TIMESTAMP))";
++             "WHERE fk_user = " << uid;
+     result = PQexec(connection, query.str().c_str());
+     }
  
  if (PQresultStatus(result) != PGRES_TUPLES_OK)
      {
@@@ -726,7 -745,7 +733,7 @@@ return 0
  
  //-----------------------------------------------------------------------------
  int POSTGRESQL_STORE::RestoreUserConf(USER_CONF * conf,
-                                     const string & login) const
+                                     const std::string & login) const
  {
  STG_LOCKER lock(&mutex, __FILE__, __LINE__);
  
@@@ -761,21 -780,23 +768,23 @@@ if (EscapeString(elogin)
      return -1;
      }
  
- std::stringstream query;
- query << "SELECT tb_users.pk_user, tb_users.address, tb_users.always_online, "
-                 "tb_users.credit, tb_users.credit_expire, tb_users.disabled, "
-                 "tb_users.disabled_detail_stat, tb_users.email, tb_users.grp, "
-                 "tb_users.note, tb_users.passive, tb_users.passwd, tb_users.phone, "
-                 "tb_users.real_name, tf1.name, tf2.name, tb_corporations.name "
-          "FROM tb_users LEFT JOIN tb_tariffs AS tf1 "
-                             "ON tf1.pk_tariff = tb_users.fk_tariff "
-                        "LEFT JOIN tb_tariffs AS tf2 "
-                             "ON tf2.pk_tariff = tb_users.fk_tariff_change "
-                        "LEFT JOIN tb_corporations "
-                             "ON tb_corporations.pk_corporation = tb_users.fk_corporation "
-          "WHERE tb_users.name = '" << elogin << "'";
+     {
+     std::ostringstream query;
+     query << "SELECT tb_users.pk_user, tb_users.address, tb_users.always_online, "
+                     "tb_users.credit, tb_users.credit_expire, tb_users.disabled, "
+                     "tb_users.disabled_detail_stat, tb_users.email, tb_users.grp, "
+                     "tb_users.note, tb_users.passive, tb_users.passwd, tb_users.phone, "
+                     "tb_users.real_name, tf1.name, tf2.name, tb_corporations.name "
+              "FROM tb_users LEFT JOIN tb_tariffs AS tf1 "
+                                 "ON tf1.pk_tariff = tb_users.fk_tariff "
+                            "LEFT JOIN tb_tariffs AS tf2 "
+                                 "ON tf2.pk_tariff = tb_users.fk_tariff_change "
+                            "LEFT JOIN tb_corporations "
+                                 "ON tb_corporations.pk_corporation = tb_users.fk_corporation "
+              "WHERE tb_users.name = '" << elogin << "'";
  
- result = PQexec(connection, query.str().c_str());
+     result = PQexec(connection, query.str().c_str());
+     }
  
  if (PQresultStatus(result) != PGRES_TUPLES_OK)
      {
@@@ -805,43 -826,46 +814,46 @@@ if (tuples != 1
  
  uint32_t uid;
  
- std::stringstream tuple;
- tuple << PQgetvalue(result, 0, 0) << " ";               // uid
- conf->address = PQgetvalue(result, 0, 1);               // address
- conf->alwaysOnline = !strncmp(PQgetvalue(result, 0, 2), "t", 1);
- tuple << PQgetvalue(result, 0, 3) << " ";               // credit
- conf->creditExpire = TS2Int(PQgetvalue(result, 0, 4));  // creditExpire
- conf->disabled = !strncmp(PQgetvalue(result, 0, 5), "t", 1);
- conf->disabledDetailStat = !strncmp(PQgetvalue(result, 0, 6), "t", 1);
- conf->email = PQgetvalue(result, 0, 7);                 // email
- conf->group = PQgetvalue(result, 0, 8);                 // group
- conf->note = PQgetvalue(result, 0, 9);                  // note
- conf->passive = !strncmp(PQgetvalue(result, 0, 10), "t", 1);
- conf->password = PQgetvalue(result, 0, 11);             // password
- conf->phone = PQgetvalue(result, 0, 12);                // phone
- conf->realName = PQgetvalue(result, 0, 13);             // realName
- conf->tariffName = PQgetvalue(result, 0, 14);           // tariffName
- conf->nextTariff = PQgetvalue(result, 0, 15);           // nextTariff
- conf->corp = PQgetvalue(result, 0, 16);                 // corp
+     {
+     std::stringstream tuple;
    tuple << PQgetvalue(result, 0, 0) << " ";               // uid
    conf->address = PQgetvalue(result, 0, 1);               // address
    conf->alwaysOnline = !strncmp(PQgetvalue(result, 0, 2), "t", 1);
    tuple << PQgetvalue(result, 0, 3) << " ";               // credit
    conf->creditExpire = TS2Int(PQgetvalue(result, 0, 4));  // creditExpire
    conf->disabled = !strncmp(PQgetvalue(result, 0, 5), "t", 1);
    conf->disabledDetailStat = !strncmp(PQgetvalue(result, 0, 6), "t", 1);
    conf->email = PQgetvalue(result, 0, 7);                 // email
    conf->group = PQgetvalue(result, 0, 8);                 // group
    conf->note = PQgetvalue(result, 0, 9);                  // note
    conf->passive = !strncmp(PQgetvalue(result, 0, 10), "t", 1);
    conf->password = PQgetvalue(result, 0, 11);             // password
    conf->phone = PQgetvalue(result, 0, 12);                // phone
    conf->realName = PQgetvalue(result, 0, 13);             // realName
    conf->tariffName = PQgetvalue(result, 0, 14);           // tariffName
    conf->nextTariff = PQgetvalue(result, 0, 15);           // nextTariff
    conf->corp = PQgetvalue(result, 0, 16);                 // corp
  
- PQclear(result);
    PQclear(result);
  
- if (conf->tariffName == "")
-     conf->tariffName = NO_TARIFF_NAME;
- if (conf->corp == "")
-     conf->corp = NO_CORP_NAME;
    if (conf->tariffName == "")
+         conf->tariffName = NO_TARIFF_NAME;
    if (conf->corp == "")
+         conf->corp = NO_CORP_NAME;
  
- tuple >> uid
-       >> conf->credit;
+     tuple >> uid
+           >> conf->credit;
+     }
  
- query.str("");
- query << "SELECT name FROM tb_services "
-          "WHERE pk_service IN (SELECT fk_service "
-                               "FROM tb_users_services "
-                               "WHERE fk_user = " << uid << ")";
+     {
+     std::ostringstream query;
+     query << "SELECT name FROM tb_services "
+              "WHERE pk_service IN (SELECT fk_service "
+                                   "FROM tb_users_services "
+                                   "WHERE fk_user = " << uid << ")";
  
- result = PQexec(connection, query.str().c_str());
+     result = PQexec(connection, query.str().c_str());
+     }
  
  if (PQresultStatus(result) != PGRES_TUPLES_OK)
      {
@@@ -864,12 -888,14 +876,14 @@@ for (int i = 0; i < tuples; ++i
  
  PQclear(result);
  
- query.str("");
- query << "SELECT num, data "
-          "FROM tb_users_data "
-          "WHERE fk_user = " << uid;
+     {
+     std::ostringstream query;
+     query << "SELECT num, data "
+              "FROM tb_users_data "
+              "WHERE fk_user = " << uid;
  
- result = PQexec(connection, query.str().c_str());
+     result = PQexec(connection, query.str().c_str());
+     }
  
  if (PQresultStatus(result) != PGRES_TUPLES_OK)
      {
@@@ -904,12 -930,14 +918,14 @@@ for (int i = 0; i < tuples; ++i
  
  PQclear(result);
  
- query.str("");
- query << "SELECT host(ip), masklen(ip) "
-          "FROM tb_allowed_ip "
-          "WHERE fk_user = " << uid;
+     {
+     std::ostringstream query;
+     query << "SELECT host(ip), masklen(ip) "
+              "FROM tb_allowed_ip "
+              "WHERE fk_user = " << uid;
  
- result = PQexec(connection, query.str().c_str());
+     result = PQexec(connection, query.str().c_str());
+     }
  
  if (PQresultStatus(result) != PGRES_TUPLES_OK)
      {
@@@ -958,13 -986,13 +974,13 @@@ return 0
  }
  
  //-----------------------------------------------------------------------------
- int POSTGRESQL_STORE::WriteUserChgLog(const string & login,
-                                     const string & admLogin,
+ int POSTGRESQL_STORE::WriteUserChgLog(const std::string & login,
+                                     const std::string & admLogin,
                                      uint32_t admIP,
-                                     const string & paramName,
-                                     const string & oldValue,
-                                     const string & newValue,
-                                     const string & message = "") const
+                                     const std::string & paramName,
+                                     const std::string & oldValue,
+                                     const std::string & newValue,
+                                     const std::string & message = "") const
  {
  STG_LOCKER lock(&mutex, __FILE__, __LINE__);
  
@@@ -1044,7 -1072,7 +1060,7 @@@ if (EscapeString(enew)
      return -1;
      }
  
- std::stringstream query;
+ std::ostringstream query;
  query << "SELECT sp_add_param_log_entry("
              "'" << elogin << "', "
              "'" << eadminLogin << "', CAST('"
@@@ -1081,7 -1109,7 +1097,7 @@@ return 0
  }
  
  //-----------------------------------------------------------------------------
- int POSTGRESQL_STORE::WriteUserConnect(const string & login, uint32_t ip) const
+ int POSTGRESQL_STORE::WriteUserConnect(const std::string & login, uint32_t ip) const
  {
  STG_LOCKER lock(&mutex, __FILE__, __LINE__);
  
@@@ -1116,7 -1144,7 +1132,7 @@@ if (EscapeString(elogin)
      return -1;
      }
  
- std::stringstream query;
+ std::ostringstream query;
  if (version < 6)
      {
      query << "SELECT sp_add_session_log_entry("
@@@ -1160,7 -1188,7 +1176,7 @@@ return 0
  }
  
  //-----------------------------------------------------------------------------
- int POSTGRESQL_STORE::WriteUserDisconnect(const string & login,
+ int POSTGRESQL_STORE::WriteUserDisconnect(const std::string & login,
                      const DIR_TRAFF & up,
                      const DIR_TRAFF & down,
                      const DIR_TRAFF & sessionUp,
@@@ -1214,26 -1242,28 +1230,28 @@@ if (EscapeString(ereason)
      return -1;
      }
  
- std::stringstream query;
- if (version < 6)
      {
-     // Old database version - no freeMb logging support
-     query << "SELECT sp_add_session_log_entry("
-                 "'" << elogin << "', "
-                 "CAST('" << Int2TS(stgTime) << "' AS TIMESTAMP), "
-                 "'d', CAST('0.0.0.0/0' AS INET), "
-                 << cash << ")";
-     }
- else
-     {
-     query << "SELECT sp_add_session_log_entry("
-                 "'" << elogin << "', "
-                 "CAST('" << Int2TS(stgTime) << "' AS TIMESTAMP), "
-                 "'d', CAST('0.0.0.0/0' AS INET), "
-                 << cash << ", " << freeMb << ", '" << ereason << "')";
-     }
+     std::ostringstream query;
+     if (version < 6)
+         {
+         // Old database version - no freeMb logging support
+         query << "SELECT sp_add_session_log_entry("
+                     "'" << elogin << "', "
+                     "CAST('" << Int2TS(stgTime) << "' AS TIMESTAMP), "
+                     "'d', CAST('0.0.0.0/0' AS INET), "
+                     << cash << ")";
+         }
+     else
+         {
+         query << "SELECT sp_add_session_log_entry("
+                     "'" << elogin << "', "
+                     "CAST('" << Int2TS(stgTime) << "' AS TIMESTAMP), "
+                     "'d', CAST('0.0.0.0/0' AS INET), "
+                     << cash << ", " << freeMb << ", '" << ereason << "')";
+         }
  
- result = PQexec(connection, query.str().c_str());
+     result = PQexec(connection, query.str().c_str());
+     }
  
  if (PQresultStatus(result) != PGRES_TUPLES_OK)
      {
@@@ -1279,7 -1309,7 +1297,7 @@@ PQclear(result)
  
  for (int i = 0; i < DIR_NUM; ++i)
      {
-     std::stringstream query;
+     std::ostringstream query;
      query << "INSERT INTO tb_sessions_data "
                  "(fk_session_log, "
                   "dir_num, "
@@@ -1322,9 -1352,9 +1340,9 @@@ return 0
  }
  
  //-----------------------------------------------------------------------------
- int POSTGRESQL_STORE::WriteDetailedStat(const map<IP_DIR_PAIR, STAT_NODE> & statTree,
+ int POSTGRESQL_STORE::WriteDetailedStat(const std::map<IP_DIR_PAIR, STAT_NODE> & statTree,
                                        time_t lastStat,
-                                       const string & login) const
+                                       const std::string & login) const
  {
  STG_LOCKER lock(&mutex, __FILE__, __LINE__);
  
@@@ -1359,12 -1389,12 +1377,12 @@@ if (EscapeString(elogin)
      return -1;
      }
  
- map<IP_DIR_PAIR, STAT_NODE>::const_iterator it;
std::map<IP_DIR_PAIR, STAT_NODE>::const_iterator it;
  time_t currTime = time(NULL);
  
  for (it = statTree.begin(); it != statTree.end(); ++it)
      {
-     std::stringstream query;
+     std::ostringstream query;
      query << "INSERT INTO tb_detail_stats "
                  "(till_time, from_time, fk_user, "
                   "dir_num, ip, download, upload, cost) "
@@@ -1405,131 -1435,11 +1423,131 @@@ return 0
  }
  
  //-----------------------------------------------------------------------------
- int POSTGRESQL_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year, const string & login) const
+ int POSTGRESQL_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year, const std::string & login) const
  {
  STG_LOCKER lock(&mutex, __FILE__, __LINE__);
  
 -return SaveStat(stat, login, year, month);
 +if (PQstatus(connection) != CONNECTION_OK)
 +    {
 +    printfd(__FILE__, "POSTGRESQL_STORE::SaveMonthStat(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
 +    if (Reset())
 +        {
 +        strError = "Connection lost";
 +        printfd(__FILE__, "POSTGRESQL_STORE::SaveMonthStat(): '%s'\n", strError.c_str());
 +        return -1;
 +        }
 +    }
 +
 +if (StartTransaction())
 +    {
 +    printfd(__FILE__, "POSTGRESQL_STORE::SaveMonthStat(): 'Failed to start transaction'\n");
 +    return -1;
 +    }
 +
 +std::string elogin = login;
 +
 +if (EscapeString(elogin))
 +    {
 +    printfd(__FILE__, "POSTGRESQL_STORE::SaveMonthStat(): 'Failed to escape login'\n");
 +    if (RollbackTransaction())
 +      {
 +      printfd(__FILE__, "POSTGRESQL_STORE::SaveMonthStat(): 'Failed to rollback transaction'\n");
 +      }
 +    return -1;
 +    }
 +
 +std::string date;
 +
 +MakeDate(date, year, month);
 +
 +std::stringstream query;
 +query << "SELECT sp_add_month_stats("
 +            "'" << elogin << "',"
 +            "CAST('" << date << "' AS DATE), "
 +            "CAST(" << stat.cash << " AS dm_money), "
 +            "CAST(" << stat.freeMb << " AS dm_money), "
 +            "CAST('" << Int2TS(stat.lastActivityTime) << "' AS TIMESTAMP), "
 +            "CAST(" << stat.lastCashAdd << " AS dm_money), "
 +            "CAST('" << Int2TS(stat.lastCashAddTime) << "' AS TIMESTAMP), "
 +            "CAST(" << stat.passiveTime << " AS INTEGER))";
 +
 +PGresult * result = PQexec(connection, query.str().c_str());
 +
 +if (PQresultStatus(result) != PGRES_TUPLES_OK)
 +    {
 +    strError = PQresultErrorMessage(result);
 +    PQclear(result);
 +    printfd(__FILE__, "POSTGRESQL_STORE::SaveMonthStat(): '%s'\n", strError.c_str());
 +    if (RollbackTransaction())
 +      {
 +      printfd(__FILE__, "POSTGRESQL_STORE::SaveMonthStat(): 'Failed to rollback transaction'\n");
 +      }
 +    return -1;
 +    }
 +
 +int tuples = PQntuples(result);
 +
 +if (tuples != 1)
 +    {
 +    strError = "Failed to fetch month stat's ID";
 +    printfd(__FILE__, "POSTGRESQL_STORE::SaveMonthStat(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
 +    PQclear(result);
 +    if (RollbackTransaction())
 +      {
 +      printfd(__FILE__, "POSTGRESQL_STORE::SaveMonthStat(): 'Failed to rollback transaction'\n");
 +      }
 +    return -1;
 +    }
 +
 +uint32_t sid;
 +
 +if (str2x(PQgetvalue(result, 0, 0), sid))
 +    {
 +    strError = "Failed to convert string to int";
 +    printfd(__FILE__, "POSTGRESQL_STORE::SaveMonthStat(): '%s'\n", strError.c_str());
 +    PQclear(result);
 +    if (RollbackTransaction())
 +      {
 +      printfd(__FILE__, "POSTGRESQL_STORE::SaveMonthStat(): 'Failed to rollback transaction'\n");
 +      }
 +    return -1;
 +    }
 +
 +PQclear(result);
 +
 +for (int dir = 0; dir < DIR_NUM; ++dir)
 +    {
 +    query.str("");
 +    query << "SELECT sp_add_month_stats_traffic ("
 +                << sid << ", "
 +                "CAST(" << dir << " AS SMALLINT), "
 +                "CAST(" << stat.up[dir] << " AS BIGINT), "
 +                "CAST(" << stat.down[dir] << " AS BIGINT))";
 +
 +    result = PQexec(connection, query.str().c_str());
 +
 +    if (PQresultStatus(result) != PGRES_TUPLES_OK)
 +        {
 +        strError = PQresultErrorMessage(result);
 +        PQclear(result);
 +        printfd(__FILE__, "POSTGRESQL_STORE::SaveMonthStat(): '%s'\n", strError.c_str());
 +        if (RollbackTransaction())
 +            {
 +            printfd(__FILE__, "POSTGRESQL_STORE::SaveMonthStat(): 'Failed to rollback transaction'\n");
 +            }
 +        return -1;
 +        }
 +
 +    PQclear(result);
 +    }
 +
 +if (CommitTransaction())
 +    {
 +    printfd(__FILE__, "POSTGRESQL_STORE::SaveMonthStat(): 'Failed to commit transaction'\n");
 +    return -1;
 +    }
 +
 +return 0;
  }
  
  //-----------------------------------------------------------------------------
@@@ -1538,21 -1448,23 +1556,23 @@@ int POSTGRESQL_STORE::SaveUserServices(
  {
  PGresult * result;
  
- std::stringstream query;
- query << "DELETE FROM tb_users_services WHERE fk_user = " << uid;
+     {
+     std::ostringstream query;
+     query << "DELETE FROM tb_users_services WHERE fk_user = " << uid;
  
- result = PQexec(connection, query.str().c_str());
+     result = PQexec(connection, query.str().c_str());
+     if (PQresultStatus(result) != PGRES_COMMAND_OK)
+         {
+         strError = PQresultErrorMessage(result);
+         PQclear(result);
+         printfd(__FILE__, "POSTGRESQL_STORE::SaveUserServices(): '%s'\n", strError.c_str());
+         return -1;
+         }
  
- if (PQresultStatus(result) != PGRES_COMMAND_OK)
-     {
-     strError = PQresultErrorMessage(result);
      PQclear(result);
-     printfd(__FILE__, "POSTGRESQL_STORE::SaveUserServices(): '%s'\n", strError.c_str());
-     return -1;
      }
  
- PQclear(result);
  std::vector<std::string>::const_iterator it;
  
  for (it = services.begin(); it != services.end(); ++it)
          return -1;
          }
  
-     std::stringstream query;
+     std::ostringstream query;
      query << "INSERT INTO tb_users_services "
                  "(fk_user, fk_service) "
               "VALUES "
@@@ -1596,10 -1508,12 +1616,12 @@@ int POSTGRESQL_STORE::SaveUserIPs(uint3
  {
  PGresult * result;
  
- std::stringstream query;
- query << "DELETE FROM tb_allowed_ip WHERE fk_user = " << uid;
+     {
+     std::ostringstream query;
+     query << "DELETE FROM tb_allowed_ip WHERE fk_user = " << uid;
  
- result = PQexec(connection, query.str().c_str());
+     result = PQexec(connection, query.str().c_str());
+     }
  
  if (PQresultStatus(result) != PGRES_COMMAND_OK)
      {
  
  PQclear(result);
  
- for (int i = 0; i < ips.Count(); ++i)
+ for (size_t i = 0; i < ips.Count(); ++i)
      {
-     std::stringstream query;
+     std::ostringstream query;
      query << "INSERT INTO tb_allowed_ip "
                  "(fk_user, ip) "
               "VALUES "
@@@ -1653,7 -1567,7 +1675,7 @@@ for (unsigned i = 0; i < data.size(); +
  
      PGresult * result;
  
-     std::stringstream query;
+     std::ostringstream query;
      query << "SELECT sp_set_user_data("
                  << uid << ", "
                  << "CAST(" << i << " AS SMALLINT), "