]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/store/postgresql/postgresql_store_services.cpp
Prevent memory leak in smux plugin
[stg.git] / projects / stargazer / plugins / store / postgresql / postgresql_store_services.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 /*
23  *  Services manipulation methods
24  *
25  *  $Revision: 1.2 $
26  *  $Date: 2009/06/09 12:32:40 $
27  *
28  */
29
30 #include <string>
31 #include <vector>
32 #include <sstream>
33
34 #include <libpq-fe.h>
35
36 #include "postgresql_store.h"
37 #include "stg/locker.h"
38
39 //-----------------------------------------------------------------------------
40 int POSTGRESQL_STORE::GetServicesList(vector<string> * servicesList) const
41 {
42 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
43
44 if (PQstatus(connection) != CONNECTION_OK)
45     {
46     printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
47     if (Reset())
48         {
49         strError = "Connection lost";
50         printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): '%s'\n", strError.c_str());
51         return -1;
52         }
53     }
54
55 PGresult * result;
56
57 if (StartTransaction())
58     {
59     printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Failed to start transaction'\n");
60     return -1;
61     }
62
63 result = PQexec(connection, "SELECT name FROM tb_services");
64
65 if (PQresultStatus(result) != PGRES_TUPLES_OK)
66     {
67     strError = PQresultErrorMessage(result);
68     PQclear(result);
69     printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): '%s'\n", strError.c_str());
70     if (RollbackTransaction())
71         {
72         printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Failed to rollback transaction'\n");
73         }
74     return -1;
75     }
76
77 int tuples = PQntuples(result);
78
79 for (int i = 0; i < tuples; ++i)
80     {
81     servicesList->push_back(PQgetvalue(result, i, 0));
82     }
83
84 PQclear(result);
85
86 if (CommitTransaction())
87     {
88     printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Failed to commit transaction'\n");
89     return -1;
90     }
91
92 return 0;
93 }
94
95 //-----------------------------------------------------------------------------
96 int POSTGRESQL_STORE::SaveService(const SERVICE_CONF & sc) const
97 {
98 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
99
100 if (PQstatus(connection) != CONNECTION_OK)
101     {
102     printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
103     if (Reset())
104         {
105         strError = "Connection lost";
106         printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): '%s'\n", strError.c_str());
107         return -1;
108         }
109     }
110
111 PGresult * result;
112
113 if (StartTransaction())
114     {
115     printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to start transaction'\n");
116     return -1;
117     }
118
119 std::string ename = sc.name;
120 std::string ecomment = sc.comment;
121
122 if (EscapeString(ename))
123     {
124     printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to escape name'\n");
125     if (RollbackTransaction())
126         {
127         printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to rollback transaction'\n");
128         }
129     return -1;
130     }
131
132 if (EscapeString(ecomment))
133     {
134     printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to escape comment'\n");
135     if (RollbackTransaction())
136         {
137         printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to rollback transaction'\n");
138         }
139     return -1;
140     }
141
142 std::stringstream query;
143 query << "UPDATE tb_services SET "
144           << "comment = '" << ecomment << "', "
145           << "cost = " << sc.cost << ", "
146           << "pay_day = " << sc.payDay << " "
147       << "WHERE name = '" << ename << "'";
148
149 result = PQexec(connection, query.str().c_str());
150
151 if (PQresultStatus(result) != PGRES_COMMAND_OK)
152     {
153     strError = PQresultErrorMessage(result);
154     PQclear(result);
155     printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): '%s'\n", strError.c_str());
156     if (RollbackTransaction())
157         {
158         printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to rollback transaction'\n");
159         }
160     return -1;
161     }
162
163 PQclear(result);
164
165 if (CommitTransaction())
166     {
167     printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to commit transaction'\n");
168     return -1;
169     }
170
171 return 0;
172 }
173
174 //-----------------------------------------------------------------------------
175 int POSTGRESQL_STORE::RestoreService(SERVICE_CONF * sc,
176                                    const string & name) const
177 {
178 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
179
180 if (PQstatus(connection) != CONNECTION_OK)
181     {
182     printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
183     if (Reset())
184         {
185         strError = "Connection lost";
186         printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): '%s'\n", strError.c_str());
187         return -1;
188         }
189     }
190
191 PGresult * result;
192
193 if (StartTransaction())
194     {
195     printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to start transaction'\n");
196     return -1;
197     }
198
199 std::string ename = name;
200
201 if (EscapeString(ename))
202     {
203     printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to escape name'\n");
204     if (RollbackTransaction())
205         {
206         printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to rollback transaction'\n");
207         }
208     return -1;
209     }
210
211 std::stringstream query;
212 query << "SELECT comment, cost, pay_day FROM tb_services WHERE name = '" << ename << "'";
213
214 result = PQexec(connection, query.str().c_str());
215
216 if (PQresultStatus(result) != PGRES_TUPLES_OK)
217     {
218     strError = PQresultErrorMessage(result);
219     PQclear(result);
220     printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): '%s'\n", strError.c_str());
221     if (RollbackTransaction())
222         {
223         printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to rollback transaction'\n");
224         }
225     return -1;
226     }
227
228 int tuples = PQntuples(result);
229
230 if (tuples != 1)
231     {
232     strError = "Failed to fetch service's data";
233     printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
234     PQclear(result);
235     if (RollbackTransaction())
236         {
237         printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to rollback transaction'\n");
238         }
239     return -1;
240     }
241
242 std::stringstream tuple;
243 tuple << PQgetvalue(result, 0, 0) << " "
244       << PQgetvalue(result, 0, 1) << " "
245       << PQgetvalue(result, 0, 2);
246
247 PQclear(result);
248
249 tuple >> sc->comment
250       >> sc->cost
251       >> sc->payDay;
252
253 if (CommitTransaction())
254     {
255     printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to commit transaction'\n");
256     return -1;
257     }
258
259 return 0;
260 }
261
262 //-----------------------------------------------------------------------------
263 int POSTGRESQL_STORE::AddService(const string & name) const
264 {
265 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
266
267 if (PQstatus(connection) != CONNECTION_OK)
268     {
269     printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
270     if (Reset())
271         {
272         strError = "Connection lost";
273         printfd(__FILE__, "POSTGRESQL_STORE::AddService(): '%s'\n", strError.c_str());
274         return -1;
275         }
276     }
277
278 PGresult * result;
279
280 if (StartTransaction())
281     {
282     printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to start transaction'\n");
283     return -1;
284     }
285
286 std::string ename = name;
287
288 if (EscapeString(ename))
289     {
290     printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to escape name'\n");
291     if (RollbackTransaction())
292         {
293         printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to rollback transaction'\n");
294         }
295     return -1;
296     }
297
298 std::stringstream query;
299 query << "INSERT INTO tb_services \
300               (name, comment, cost, pay_day) \
301           VALUES \
302               ('" << ename << "', '', 0, 0)";
303
304 result = PQexec(connection, query.str().c_str());
305
306 if (PQresultStatus(result) != PGRES_COMMAND_OK)
307     {
308     strError = PQresultErrorMessage(result);
309     PQclear(result);
310     printfd(__FILE__, "POSTGRESQL_STORE::AddService(): '%s'\n", strError.c_str());
311     if (RollbackTransaction())
312         {
313         printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to rollback transaction'\n");
314         }
315     return -1;
316     }
317
318 PQclear(result);
319
320 if (CommitTransaction())
321     {
322     printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to commit transaction'\n");
323     return -1;
324     }
325
326 return 0;
327 }
328
329 //-----------------------------------------------------------------------------
330 int POSTGRESQL_STORE::DelService(const string & name) const
331 {
332 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
333
334 if (PQstatus(connection) != CONNECTION_OK)
335     {
336     printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
337     if (Reset())
338         {
339         strError = "Connection lost";
340         printfd(__FILE__, "POSTGRESQL_STORE::DelService(): '%s'\n", strError.c_str());
341         return -1;
342         }
343     }
344
345 PGresult * result;
346
347 if (StartTransaction())
348     {
349     printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to start transaction'\n");
350     return -1;
351     }
352
353 std::string ename = name;
354
355 if (EscapeString(ename))
356     {
357     printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to escape name'\n");
358     if (RollbackTransaction())
359         {
360         printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to rollback transaction'\n");
361         }
362     return -1;
363     }
364
365 std::stringstream query;
366 query << "DELETE FROM tb_services WHERE name = '" << ename << "'";
367
368 result = PQexec(connection, query.str().c_str());
369
370 if (PQresultStatus(result) != PGRES_COMMAND_OK)
371     {
372     strError = PQresultErrorMessage(result);
373     PQclear(result);
374     printfd(__FILE__, "POSTGRESQL_STORE::DelService(): '%s'\n", strError.c_str());
375     if (RollbackTransaction())
376         {
377         printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to rollback transaction'\n");
378         }
379     return -1;
380     }
381
382 PQclear(result);
383
384 if (CommitTransaction())
385     {
386     printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to commit transaction'\n");
387     return -1;
388     }
389
390 return 0;
391 }
392 //-----------------------------------------------------------------------------
393