Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
test_dbpool.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2016 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  * test_dbpool.c - test DBPool objects
59  *
60  * Stipe Tolj <stolj@wapme.de>
61  * Alexander Malysh <amalysh@kannel.org>
62  */
63 
64 #include "gwlib/gwlib.h"
65 #include "gwlib/dbpool.h"
66 
67 #ifdef HAVE_DBPOOL
68 
69 #define MAX_THREADS 1024
70 
71 static void help(void)
72 {
73  info(0, "Usage: test_dbpool [options] ...");
74  info(0, "where options are:");
75  info(0, "-v number");
76  info(0, " set log level for stderr logging");
77  info(0, "-h hostname");
78  info(0, " hostname to connect to");
79  info(0, "-u username");
80  info(0, " username to use for the login credentials");
81  info(0, "-p password");
82  info(0, " password to use for the login credentials");
83  info(0, "-d database");
84  info(0, " database to connect to (for oracle tnsname) or file to open (for sqlite)");
85  info(0, "-s number");
86  info(0, " size of the database connection pool (default: 5)");
87  info(0, "-q number");
88  info(0, " run a set of queries on the database connection pool (default: 100)");
89  info(0, "-t number");
90  info(0, " how many query client threads should be used (default: 1)");
91  info(0, "-S string");
92  info(0, " the SQL string that is performed while the queries (default: SHOW STATUS)");
93  info(0, "-T type");
94  info(0, " the type of database to use [mysql|oracle|sqlite|cassandra]");
95 }
96 
97 /* global variables */
98 static unsigned long queries = 100;
99 static Octstr *sql;
100 static unsigned int pool_size = 5;
101 
102 static enum db_type database_type = DBPOOL_MYSQL;
103 
104 static void (*client_thread)(void*) = NULL;
105 
106 #ifdef HAVE_MYSQL
107 
108 static void mysql_client_thread(void *arg)
109 {
110  unsigned long i, succeeded, failed;
111  DBPool *pool = arg;
112  List *result;
113  DBPoolConn *pconn;
114 
115  succeeded = failed = 0;
116 
117  info(0,"Client thread started with %ld queries to perform on pool", queries);
118 
119  for (i = 1; i <= queries; i++) {
120  pconn = dbpool_conn_consume(pool);
121 
122  if (pconn == NULL)
123  continue;
124 #if 1 /* selects */
125  if (dbpool_conn_select(pconn, sql, NULL, &result) == 0) {
126  long i,j;
127  for (i=0; i < gwlist_len(result); i++) {
128  List *row = gwlist_get(result, i);
129  for (j=0; j < gwlist_len(row); j++)
130  debug("", 0, "col = %ld value = '%s'", j, octstr_get_cstr(gwlist_get(row,j)));
132  }
133  succeeded++;
134  } else {
135  failed++;
136  }
137  gwlist_destroy(result, NULL);
138  dbpool_conn_produce(pconn);
139 #else /* only updates */
140  debug("", 0, "rows processed = %d ", dbpool_conn_update(pconn, sql, NULL));
141  dbpool_conn_produce(pconn);
142 #endif
143  }
144  info(0, "This thread: %ld succeeded, %ld failed.", succeeded, failed);
145 }
146 
147 static DBConf *mysql_create_conf(Octstr *user, Octstr *pass, Octstr *db, Octstr *host)
148 {
149  DBConf *conf;
150  conf = gw_malloc(sizeof(DBConf));
151  conf->mysql = gw_malloc(sizeof(MySQLConf));
152 
153  conf->mysql->username = octstr_duplicate(user);
154  conf->mysql->password = octstr_duplicate(pass);
155  conf->mysql->database = octstr_duplicate(db);
156  conf->mysql->host = octstr_duplicate(host);
157  conf->mysql->port = 3306;
158 
159  return conf;
160 }
161 #endif
162 
163 #ifdef HAVE_ORACLE
164 #include <oci.h>
165 
166 static DBConf *oracle_create_conf(Octstr *user,Octstr *pass, Octstr *db)
167 {
168  DBConf *conf;
169  conf = gw_malloc(sizeof(DBConf));
170  conf->oracle = gw_malloc(sizeof(OracleConf));
171 
172  conf->oracle->username = octstr_duplicate(user);
173  conf->oracle->password = octstr_duplicate(pass);
174  conf->oracle->tnsname = octstr_duplicate(db);
175 
176  return conf;
177 }
178 
179 struct ora_conn {
180  /* environment handle */
181  OCIEnv *envp;
182  /* context handle */
183  OCISvcCtx *svchp;
184  /* error handle */
185  OCIError *errhp;
186 };
187 
188 static void oracle_client_thread(void *arg)
189 {
190  DBPool *pool = arg;
191  DBPoolConn *pconn = NULL;
192  int i;
193  List *result;
194 
195  for (i = 1; i <= queries; i++) {
196  pconn = dbpool_conn_consume(pool);
197 
198  if (pconn == NULL)
199  continue;
200 #if 1 /* selects */
201  if (dbpool_conn_select(pconn, sql, NULL, &result) == 0) {
202  long i,j;
203  for (i=0; i < gwlist_len(result); i++) {
204  List *row = gwlist_get(result, i);
205  for (j=0; j < gwlist_len(row); j++)
206  debug("", 0, "col = %ld value = '%s'", j, octstr_get_cstr(gwlist_get(row,j)));
208  }
209  }
210  gwlist_destroy(result, NULL);
211  dbpool_conn_produce(pconn);
212 #else /* only updates */
213  debug("", 0, "rows processed = %d ", dbpool_conn_update(pconn, sql, NULL));
214  dbpool_conn_produce(pconn);
215 #endif
216  }
217 }
218 #endif
219 
220 #ifdef HAVE_SQLITE
221 #include <sqlite.h>
222 
223 static DBConf *sqlite_create_conf(Octstr *db)
224 {
225  DBConf *conf;
226  conf = gw_malloc(sizeof(DBConf));
227  conf->sqlite = gw_malloc(sizeof(SQLiteConf));
228 
229  conf->sqlite->file = octstr_duplicate(db);
230 
231  return conf;
232 }
233 
234 static int callback(void *not_used, int argc, char **argv, char **col_name)
235 {
236  int i;
237 
238  for (i = 0; i < argc; i++) {
239  debug("",0,"SQLite: result: %s = %s", col_name[i], argv[i]);
240  }
241 
242  return 0;
243 }
244 
245 static void sqlite_client_thread(void *arg)
246 {
247  unsigned long i, succeeded, failed;
248  DBPool *pool = arg;
249  char *errmsg = 0;
250 
251  succeeded = failed = 0;
252 
253  info(0,"Client thread started with %ld queries to perform on pool", queries);
254 
255  /* perform random queries on the pool */
256  for (i = 1; i <= queries; i++) {
257  DBPoolConn *pconn;
258  int state;
259 
260  /* provide us with a connection from the pool */
261  pconn = dbpool_conn_consume(pool);
262  debug("",0,"Query %ld/%ld: sqlite conn obj at %p",
263  i, queries, (void*) pconn->conn);
264 
265  state = sqlite_exec(pconn->conn, octstr_get_cstr(sql), callback, 0, &errmsg);
266  if (state != SQLITE_OK) {
267  error(0, "SQLite: %s", errmsg);
268  failed++;
269  } else {
270  succeeded++;
271  }
272 
273  /* return the connection to the pool */
274  dbpool_conn_produce(pconn);
275  }
276  info(0, "This thread: %ld succeeded, %ld failed.", succeeded, failed);
277 }
278 #endif
279 
280 #ifdef HAVE_SQLITE3
281 #include <sqlite3.h>
282 
283 static DBConf *sqlite3_create_conf(Octstr *db)
284 {
285  DBConf *conf;
286  conf = gw_malloc(sizeof(DBConf));
287  conf->sqlite3 = gw_malloc(sizeof(SQLite3Conf));
288 
289  conf->sqlite3->file = octstr_duplicate(db);
290 
291  return conf;
292 }
293 
294 static int callback3(void *not_used, int argc, char **argv, char **col_name)
295 {
296  int i;
297 
298  for (i = 0; i < argc; i++) {
299  debug("",0,"SQLite3: result: %s = %s", col_name[i], argv[i]);
300  }
301 
302  return 0;
303 }
304 
305 static void sqlite3_client_thread(void *arg)
306 {
307  unsigned long i, succeeded, failed;
308  DBPool *pool = arg;
309  char *errmsg = 0;
310 
311  succeeded = failed = 0;
312 
313  info(0,"Client thread started with %ld queries to perform on pool", queries);
314 
315  /* perform random queries on the pool */
316  for (i = 1; i <= queries; i++) {
317  DBPoolConn *pconn;
318  int state;
319 
320  /* provide us with a connection from the pool */
321  pconn = dbpool_conn_consume(pool);
322  debug("",0,"Query %ld/%ld: sqlite conn obj at %p",
323  i, queries, (void*) pconn->conn);
324 
325  state = sqlite3_exec(pconn->conn, octstr_get_cstr(sql), callback3, 0, &errmsg);
326  if (state != SQLITE_OK) {
327  error(0, "SQLite3: %s", errmsg);
328  failed++;
329  } else {
330  succeeded++;
331  }
332 
333  /* return the connection to the pool */
334  dbpool_conn_produce(pconn);
335  }
336  info(0, "This thread: %ld succeeded, %ld failed.", succeeded, failed);
337 }
338 #endif
339 
340 #ifdef HAVE_CASS
341 
342 static void cass_client_thread(void *arg)
343 {
344  unsigned long i, succeeded, failed;
345  DBPool *pool = arg;
346  List *result;
347  DBPoolConn *pconn;
348 
349  succeeded = failed = 0;
350 
351  info(0,"Client thread started with %ld queries to perform on pool", queries);
352 
353  for (i = 1; i <= queries; i++) {
354  pconn = dbpool_conn_consume(pool);
355 
356  if (pconn == NULL)
357  continue;
358 #if 1 /* selects */
359  if (dbpool_conn_select(pconn, sql, NULL, &result) == 0) {
360  long i,j;
361  for (i=0; i < gwlist_len(result); i++) {
362  List *row = gwlist_get(result, i);
363  for (j=0; j < gwlist_len(row); j++)
364  debug("", 0, "col = %ld value = '%s'", j, octstr_get_cstr(gwlist_get(row,j)));
366  }
367  succeeded++;
368  } else {
369  failed++;
370  }
371  gwlist_destroy(result, NULL);
372  dbpool_conn_produce(pconn);
373 #else /* only updates */
374  debug("", 0, "rows processed = %d ", dbpool_conn_update(pconn, sql, NULL));
375  dbpool_conn_produce(pconn);
376 #endif
377  }
378  info(0, "This thread: %ld succeeded, %ld failed.", succeeded, failed);
379 }
380 
381 static DBConf *cass_create_conf(Octstr *user, Octstr *pass, Octstr *db, Octstr *host)
382 {
383  DBConf *conf;
384  conf = gw_malloc(sizeof(DBConf));
385  conf->cass = gw_malloc(sizeof(CassConf));
386 
387  conf->cass->username = octstr_duplicate(user);
388  conf->cass->password = octstr_duplicate(pass);
389  conf->cass->database = octstr_duplicate(db);
390  conf->cass->host = octstr_duplicate(host);
391 
392  return conf;
393 }
394 #endif
395 
396 static void inc_dec_thread(void *arg)
397 {
398  DBPool *pool = arg;
399  int ret;
400 
401  /* decrease */
402  info(0,"Decreasing pool by half of size, which is %d connections", abs(pool_size/2));
403  ret = dbpool_decrease(pool, abs(pool_size/2));
404  debug("",0,"Decreased by %d connections", ret);
405  debug("",0,"Connections within pool: %ld", dbpool_conn_count(pool));
406 
407  /* increase */
408  info(0,"Increasing pool again by %d connections", pool_size);
409  ret = dbpool_increase(pool, pool_size);
410  debug("",0,"Increased by %d connections", ret);
411  debug("",0,"Connections within pool: %ld", dbpool_conn_count(pool));
412 }
413 
414 int main(int argc, char **argv)
415 {
416  DBPool *pool;
417  DBConf *conf = NULL; /* for compiler please */
418  unsigned int num_threads = 1;
419  unsigned long i;
420  int opt;
421  time_t start = 0, end = 0;
422  double run_time;
423  Octstr *user, *pass, *db, *host, *db_type;
424  int j, bail_out;
425 
426  user = pass = db = host = db_type = NULL;
427 
428  gwlib_init();
429 
430  sql = octstr_imm("SHOW STATUS");
431 
432  while ((opt = getopt(argc, argv, "v:h:u:p:d:s:q:t:S:T:")) != EOF) {
433  switch (opt) {
434  case 'v':
436  break;
437 
438  case 'h':
439  host = octstr_create(optarg);
440  break;
441 
442  case 'u':
443  user = octstr_create(optarg);
444  break;
445 
446  case 'p':
447  pass = octstr_create(optarg);
448  break;
449 
450  case 'd':
451  db = octstr_create(optarg);
452  break;
453 
454  case 'S':
455  octstr_destroy(sql);
456  sql = octstr_create(optarg);
457  break;
458 
459  case 's':
460  pool_size = atoi(optarg);
461  break;
462 
463  case 'q':
464  queries = atoi(optarg);
465  break;
466 
467  case 't':
468  num_threads = atoi(optarg);
469  break;
470 
471  case 'T':
472  db_type = octstr_create(optarg);
473  break;
474 
475  case '?':
476  default:
477  error(0, "Invalid option %c", opt);
478  help();
479  panic(0, "Stopping.");
480  }
481  }
482 
483  if (!optind) {
484  help();
485  exit(0);
486  }
487 
488  if (!db_type) {
489  info(0, "No database type given assuming MySQL.");
490  }
491  else if (octstr_case_compare(db_type, octstr_imm("mysql")) == 0) {
492  info(0, "Do tests for mysql database.");
493  database_type = DBPOOL_MYSQL;
494  }
495  else if (octstr_case_compare(db_type, octstr_imm("oracle")) == 0) {
496  info(0, "Do tests for oracle database.");
497  database_type = DBPOOL_ORACLE;
498  }
499  else if (octstr_case_compare(db_type, octstr_imm("sqlite")) == 0) {
500  info(0, "Do tests for sqlite database.");
501  database_type = DBPOOL_SQLITE;
502  }
503  else if (octstr_case_compare(db_type, octstr_imm("sqlite3")) == 0) {
504  info(0, "Do tests for sqlite3 database.");
505  database_type = DBPOOL_SQLITE3;
506  }
507  else if (octstr_case_compare(db_type, octstr_imm("cassandra")) == 0) {
508  info(0, "Do tests for cassandra database.");
509  database_type = DBPOOL_CASS;
510  }
511  else {
512  panic(0, "Unknown database type '%s'", octstr_get_cstr(db_type));
513  }
514 
515  /* check if we have the database connection details */
516  switch (database_type) {
517  case DBPOOL_ORACLE:
518  bail_out = (!user || !pass || !db) ? 1 : 0;
519  break;
520  case DBPOOL_SQLITE:
521  case DBPOOL_SQLITE3:
522  bail_out = (!db) ? 1 : 0;
523  break;
524  case DBPOOL_CASS:
525  bail_out = (!host || !db) ? 1 : 0;
526  break;
527  default:
528  bail_out = (!host || !user || !pass || !db) ? 1 : 0;
529  break;
530  }
531  if (bail_out) {
532  help();
533  panic(0, "Database connection details are not fully provided!");
534  }
535 
536  for (j = 0; j < 1; j++) {
537 
538  /* create DBConf */
539  switch (database_type) {
540 #ifdef HAVE_MYSQL
541  case DBPOOL_MYSQL:
542  conf = mysql_create_conf(user,pass,db,host);
543  client_thread = mysql_client_thread;
544  break;
545 #endif
546 #ifdef HAVE_ORACLE
547  case DBPOOL_ORACLE:
548  conf = oracle_create_conf(user, pass, db);
549  client_thread = oracle_client_thread;
550  break;
551 #endif
552 #ifdef HAVE_SQLITE
553  case DBPOOL_SQLITE:
554  conf = sqlite_create_conf(db);
555  client_thread = sqlite_client_thread;
556  break;
557 #endif
558 #ifdef HAVE_SQLITE3
559  case DBPOOL_SQLITE3:
560  conf = sqlite3_create_conf(db);
561  client_thread = sqlite3_client_thread;
562  break;
563 #endif
564 #ifdef HAVE_CASS
565  case DBPOOL_CASS:
566  conf = cass_create_conf(user,pass,db,host);
567  client_thread = cass_client_thread;
568  break;
569 #endif
570  default:
571  panic(0, "ooops ....");
572  };
573 
574  /* create */
575  info(0,"Creating database pool to `%s' with %d connections type '%s'.",
576  (host ? octstr_get_cstr(host) : octstr_get_cstr(db)), pool_size, octstr_get_cstr(db_type));
577  pool = dbpool_create(database_type, conf, pool_size);
578  debug("",0,"Connections within pool: %ld", dbpool_conn_count(pool));
579  if (dbpool_conn_count(pool) == 0) {
580  panic(0, "Unable to start without DBConns...");
581  exit(1);
582  }
583 
584  for (i = 0; i < num_threads; ++i) {
585  if (gwthread_create(inc_dec_thread, pool) == -1)
586  panic(0, "Could not create thread %ld", i);
587  }
589 
590  info(0, "Connections within pool: %ld", dbpool_conn_count(pool));
591  info(0, "Checked pool, %d connections still active and ok", dbpool_check(pool));
592 
593  /* queries */
594  info(0,"SQL query is `%s'", octstr_get_cstr(sql));
595  time(&start);
596  for (i = 0; i < num_threads; ++i) {
597 #if 0
598  if (gwthread_create(inc_dec_thread, pool) == -1)
599  panic(0, "Couldnot create thread %ld", i);
600 #endif
601  if (gwthread_create(client_thread, pool) == -1)
602  panic(0, "Couldnot create thread %ld", i);
603  }
604 
606  time(&end);
607 
608  run_time = difftime(end, start);
609  info(0, "%ld requests in %.2f seconds, %.2f requests/s.",
610  (queries * num_threads), run_time, (float) (queries * num_threads) / (run_time==0?1:run_time));
611 
612  /* check all active connections */
613  debug("",0,"Connections within pool: %ld", dbpool_conn_count(pool));
614  info(0,"Checked pool, %d connections still active and ok", dbpool_check(pool));
615 
616  info(0,"Destroying pool");
617  dbpool_destroy(pool);
618 
619  } /* for loop */
620 
621  octstr_destroy(sql);
622  octstr_destroy(db_type);
623  octstr_destroy(user);
624  octstr_destroy(pass);
625  octstr_destroy(db);
626  octstr_destroy(host);
627  gwlib_shutdown();
628 
629  return 0;
630 }
631 
632 
633 #endif /* HAVE_DBPOOL */
void error(int err, const char *fmt,...)
Definition: log.c:612
void info(int err, const char *fmt,...)
Definition: log.c:636
Octstr * password
Definition: dbpool.h:119
db_type
Definition: dbpool.h:76
void gwthread_join_all(void)
unsigned int dbpool_check(DBPool *p)
long dbpool_conn_count(DBPool *p)
SQLite3Conf * sqlite3
Definition: dbpool.h:170
DBPool * dbpool_create(enum db_type db_type, DBConf *conf, unsigned int connections)
Octstr * file
Definition: dbpool.h:133
Octstr * database
Definition: dbpool.h:160
long gwlist_len(List *list)
Definition: list.c:166
static void client_thread(void *arg)
Definition: test_http.c:194
void * gwlist_get(List *list, long pos)
Definition: list.c:292
int optind
Definition: attgetopt.c:80
static Octstr * host
Definition: fakesmsc.c:121
unsigned int dbpool_decrease(DBPool *p, unsigned int conn)
unsigned int dbpool_increase(DBPool *p, unsigned int conn)
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
void dbpool_conn_produce(DBPoolConn *conn)
Octstr * username
Definition: dbpool.h:118
int getopt(int argc, char **argv, char *opts)
Definition: attgetopt.c:84
int main(void)
Definition: check_counter.c:93
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
void log_set_output_level(enum output_level level)
Definition: log.c:217
CassConf * cass
Definition: dbpool.h:173
Octstr * password
Definition: dbpool.h:103
#define octstr_duplicate(ostr)
Definition: octstr.h:187
int octstr_case_compare(const Octstr *os1, const Octstr *os2)
Definition: octstr.c:901
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define gwthread_create(func, arg)
Definition: gwthread.h:90
#define octstr_create(cstr)
Definition: octstr.h:125
void octstr_destroy_item(void *os)
Definition: octstr.c:334
Octstr * host
Definition: dbpool.h:100
Definition: dbpool.h:164
Octstr * tnsname
Definition: dbpool.h:120
void dbpool_destroy(DBPool *p)
int dbpool_conn_update(DBPoolConn *conn, const Octstr *sql, List *binds)
Octstr * host
Definition: dbpool.h:156
Definition: octstr.c:118
MySQLConf * mysql
Definition: dbpool.h:166
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
char * optarg
Definition: attgetopt.c:82
#define panic
Definition: log.h:87
static void help(void)
Definition: drive_smpp.c:460
void gwlib_shutdown(void)
Definition: gwlib.c:94
Octstr * username
Definition: dbpool.h:102
Octstr * database
Definition: dbpool.h:104
int dbpool_conn_select(DBPoolConn *conn, const Octstr *sql, List *binds, List **result)
long port
Definition: dbpool.h:101
DBPoolConn * dbpool_conn_consume(DBPool *p)
void gwlib_init(void)
Definition: gwlib.c:78
void * conn
Definition: dbpool.h:95
Octstr * file
Definition: dbpool.h:128
Octstr * password
Definition: dbpool.h:159
Octstr * username
Definition: dbpool.h:158
Definition: list.c:102
static int start
SQLiteConf * sqlite
Definition: dbpool.h:169
OracleConf * oracle
Definition: dbpool.h:168
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.