]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/store/postgresql/postgresql_store.cpp
2146d66483f32dc9179122828cbe0b146584694d
[stg.git] / projects / stargazer / plugins / store / postgresql / postgresql_store.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  *  This file contains a realization of a base postgresql-storage plugin class
23  *
24  *  v. 1.3
25  *  FreeMb logging on disconnects added
26  *
27  *  v. 1.2
28  *  Reconnection on faults added
29  *
30  *  v. 1.1
31  *  tb_stats removed
32  *
33  *  v. 1.0
34  *  Initial implementation
35  *
36  *  $Revision: 1.5 $
37  *  $Date: 2010/01/06 10:43:48 $
38  *
39  */
40
41 #include "postgresql_store.h"
42
43 #include "postgresql_store_utils.h"
44 #include "postgresql_store.h"
45
46 #include "stg/common.h" // str2x, printfd
47
48 #include <string>
49 #include <vector>
50
51 #include <libpq-fe.h>
52
53 extern "C" STG::Store* GetStore()
54 {
55     static POSTGRESQL_STORE plugin;
56     return &plugin;
57 }
58
59 //-----------------------------------------------------------------------------
60 POSTGRESQL_STORE::POSTGRESQL_STORE()
61     : versionString("postgresql_store v.1.3"),
62       server("localhost"),
63       database("stargazer"),
64       user("stg"),
65       password("123456"),
66       clientEncoding("KOI8"),
67       version(0),
68       retries(3),
69       connection(NULL),
70       logger(STG::PluginLogger::get("store_postgresql"))
71 {
72 pthread_mutex_init(&mutex, NULL);
73 }
74 //-----------------------------------------------------------------------------
75 POSTGRESQL_STORE::~POSTGRESQL_STORE()
76 {
77 if (connection)
78     {
79     PQfinish(connection);
80     }
81 pthread_mutex_destroy(&mutex);
82 }
83 //-----------------------------------------------------------------------------
84 int POSTGRESQL_STORE::ParseSettings()
85 {
86 std::vector<STG::ParamValue>::iterator i;
87
88 for(i = settings.moduleParams.begin(); i != settings.moduleParams.end(); ++i)
89     {
90     if (i->value.empty())
91         continue;
92     std::string s = ToLower(i->param);
93     if (s == "server")
94         {
95         server = i->value.front();
96         }
97     if (s == "database")
98         {
99         database = i->value.front();
100         }
101     if (s == "user")
102         {
103         user = i->value.front();
104         }
105     if (s == "password")
106         {
107         password = i->value.front();
108         }
109     if (s == "retries")
110         {
111         if (str2x(i->value.front(), retries))
112             {
113             strError = "Invalid 'retries' value";
114             printfd(__FILE__, "POSTGRESQL_STORE::ParseSettings(): '%s'\n", strError.c_str());
115             return -1;
116             }
117         }
118     }
119
120 clientEncoding = "KOI8";
121
122 return Connect();
123 }
124 //-----------------------------------------------------------------------------
125 int POSTGRESQL_STORE::Connect()
126 {
127 std::string params;
128 params = "host=" + server + " "
129        + "dbname=" + database + " "
130        + "user=" + user + " "
131        + "password=" + password;
132
133 connection = PQconnectdb(params.c_str());
134
135 if (PQstatus(connection) != CONNECTION_OK)
136     {
137     strError = PQerrorMessage(connection);
138     printfd(__FILE__, "POSTGRESQL_STORE::Connect(): '%s'\n", strError.c_str());
139     // Will try to connect later
140     return 0;
141     }
142
143 if (PQsetClientEncoding(connection, clientEncoding.c_str()))
144     {
145     strError = PQerrorMessage(connection);
146     printfd(__FILE__, "POSTGRESQL_STORE::Connect(): '%s'\n", strError.c_str());
147     return 1;
148     }
149
150 return CheckVersion();
151 }
152 //-----------------------------------------------------------------------------
153 int POSTGRESQL_STORE::Reset() const
154 {
155 for (int i = 0; i < retries && PQstatus(connection) != CONNECTION_OK; ++i)
156     {
157     struct timespec ts = {1, 0};
158     nanosleep(&ts, NULL);
159     PQreset(connection);
160     }
161
162 if (PQstatus(connection) != CONNECTION_OK)
163     {
164     strError = PQerrorMessage(connection);
165     printfd(__FILE__, "POSTGRESQL_STORE::Reset(): '%s'\n", strError.c_str());
166     return 1;
167     }
168
169 if (PQsetClientEncoding(connection, clientEncoding.c_str()))
170     {
171     strError = PQerrorMessage(connection);
172     printfd(__FILE__, "POSTGRESQL_STORE::Reset(): '%s'\n", strError.c_str());
173     return -1;
174     }
175
176 return CheckVersion();
177 }
178 //-----------------------------------------------------------------------------
179 int POSTGRESQL_STORE::CheckVersion() const
180 {
181
182 if (StartTransaction())
183     {
184     strError = "Failed to start transaction";
185     printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
186     return -1;
187     }
188
189 PGresult * result = PQexec(connection, "SELECT MAX(version) FROM tb_info");
190
191 if (PQresultStatus(result) != PGRES_TUPLES_OK)
192     {
193     strError = PQresultErrorMessage(result);
194     PQclear(result);
195     printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n");
196     RollbackTransaction();
197     return -1;
198     }
199
200 if (str2x(PQgetvalue(result, 0, 0), version))
201     {
202     strError = "Invalid DB version";
203     PQclear(result);
204     RollbackTransaction();
205     printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
206     return -1;
207     }
208
209 PQclear(result);
210
211 if (version < DB_MIN_VERSION)
212     {
213     strError = "DB version too old";
214     RollbackTransaction();
215     printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
216     return -1;
217     }
218
219 if (version < 6)
220     {
221     printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): I recommend you to upgrade your DB to higher version to support FreeMb logging on disconnect. Current version is %d\n", version);
222     }
223
224 if (CommitTransaction())
225     {
226     strError = "Failed to commit transaction";
227     printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
228     return -1;
229     }
230
231 logger("POSTGRESQL_STORE: Current DB schema version: %d", version);
232
233 return 0;
234 }
235 //-----------------------------------------------------------------------------