00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 #include "gwlib/gwlib.h"
00065 #include "gwlib/dbpool.h"
00066
00067 #ifdef HAVE_DBPOOL
00068
00069 #define MAX_THREADS 1024
00070
00071 static void help(void)
00072 {
00073 info(0, "Usage: test_dbpool [options] ...");
00074 info(0, "where options are:");
00075 info(0, "-v number");
00076 info(0, " set log level for stderr logging");
00077 info(0, "-h hostname");
00078 info(0, " hostname to connect to");
00079 info(0, "-u username");
00080 info(0, " username to use for the login credentials");
00081 info(0, "-p password");
00082 info(0, " password to use for the login credentials");
00083 info(0, "-d database");
00084 info(0, " database to connect to (for oracle tnsname) or file to open (for sqlite)");
00085 info(0, "-s number");
00086 info(0, " size of the database connection pool (default: 5)");
00087 info(0, "-q number");
00088 info(0, " run a set of queries on the database connection pool (default: 100)");
00089 info(0, "-t number");
00090 info(0, " how many query client threads should be used (default: 1)");
00091 info(0, "-S string");
00092 info(0, " the SQL string that is performed while the queries (default: SHOW STATUS)");
00093 info(0, "-T type");
00094 info(0, " the type of database to use [mysql|oracle|sqlite]");
00095 }
00096
00097
00098 static unsigned long queries = 100;
00099 static Octstr *sql;
00100 static unsigned int pool_size = 5;
00101
00102 static enum db_type database_type = DBPOOL_MYSQL;
00103
00104 static void (*client_thread)(void*) = NULL;
00105
00106 #ifdef HAVE_MYSQL
00107 #include <mysql.h>
00108
00109 static void mysql_client_thread(void *arg)
00110 {
00111 unsigned long i, succeeded, failed;
00112 DBPool *pool = arg;
00113
00114 succeeded = failed = 0;
00115
00116 info(0,"Client thread started with %ld queries to perform on pool", queries);
00117
00118
00119 for (i = 1; i <= queries; i++) {
00120 DBPoolConn *pconn;
00121 int state;
00122 MYSQL_RES *result;
00123
00124
00125 pconn = dbpool_conn_consume(pool);
00126 debug("",0,"Query %ld/%ld: mysql thread id %ld obj at %p",
00127 i, queries, mysql_thread_id(pconn->conn), (void*) pconn->conn);
00128
00129 state = mysql_query(pconn->conn, octstr_get_cstr(sql));
00130 if (state != 0) {
00131 error(0, "MYSQL: %s", mysql_error(pconn->conn));
00132 failed++;
00133 } else {
00134 succeeded++;
00135 }
00136 result = mysql_store_result(pconn->conn);
00137 mysql_free_result(result);
00138
00139
00140 dbpool_conn_produce(pconn);
00141 }
00142 info(0, "This thread: %ld succeeded, %ld failed.", succeeded, failed);
00143 }
00144
00145 static DBConf *mysql_create_conf(Octstr *user, Octstr *pass, Octstr *db, Octstr *host)
00146 {
00147 DBConf *conf;
00148 conf = gw_malloc(sizeof(DBConf));
00149 conf->mysql = gw_malloc(sizeof(MySQLConf));
00150
00151 conf->mysql->username = octstr_duplicate(user);
00152 conf->mysql->password = octstr_duplicate(pass);
00153 conf->mysql->database = octstr_duplicate(db);
00154 conf->mysql->host = octstr_duplicate(host);
00155
00156 return conf;
00157 }
00158 #endif
00159
00160 #ifdef HAVE_ORACLE
00161 #include <oci.h>
00162
00163 static DBConf *oracle_create_conf(Octstr *user,Octstr *pass, Octstr *db)
00164 {
00165 DBConf *conf;
00166 conf = gw_malloc(sizeof(DBConf));
00167 conf->oracle = gw_malloc(sizeof(OracleConf));
00168
00169 conf->oracle->username = octstr_duplicate(user);
00170 conf->oracle->password = octstr_duplicate(pass);
00171 conf->oracle->tnsname = octstr_duplicate(db);
00172
00173 return conf;
00174 }
00175
00176 struct ora_conn {
00177
00178 OCIEnv *envp;
00179
00180 OCISvcCtx *svchp;
00181
00182 OCIError *errhp;
00183 };
00184
00185 static void oracle_client_thread(void *arg)
00186 {
00187 DBPool *pool = arg;
00188 DBPoolConn *pconn = NULL;
00189 int i;
00190 List *result;
00191
00192 for (i = 1; i <= queries; i++) {
00193 pconn = dbpool_conn_consume(pool);
00194
00195 if (pconn == NULL)
00196 continue;
00197 #if 1
00198 if (dbpool_conn_select(pconn, sql, NULL, &result) == 0) {
00199 long i,j;
00200 for (i=0; i < gwlist_len(result); i++) {
00201 List *row = gwlist_get(result, i);
00202 for (j=0; j < gwlist_len(row); j++)
00203 debug("", 0, "col = %ld value = '%s'", j, octstr_get_cstr(gwlist_get(row,j)));
00204 gwlist_destroy(row, octstr_destroy_item);
00205 }
00206 }
00207 gwlist_destroy(result, NULL);
00208 dbpool_conn_produce(pconn);
00209 #else
00210 debug("", 0, "rows processed = %d ", dbpool_conn_update(pconn, sql, NULL));
00211 dbpool_conn_produce(pconn);
00212 #endif
00213 }
00214 }
00215 #endif
00216
00217 #ifdef HAVE_SQLITE
00218 #include <sqlite.h>
00219
00220 static DBConf *sqlite_create_conf(Octstr *db)
00221 {
00222 DBConf *conf;
00223 conf = gw_malloc(sizeof(DBConf));
00224 conf->sqlite = gw_malloc(sizeof(SQLiteConf));
00225
00226 conf->sqlite->file = octstr_duplicate(db);
00227
00228 return conf;
00229 }
00230
00231 static int callback(void *not_used, int argc, char **argv, char **col_name)
00232 {
00233 int i;
00234
00235 for (i = 0; i < argc; i++) {
00236 debug("",0,"SQLite: result: %s = %s", col_name[i], argv[i]);
00237 }
00238
00239 return 0;
00240 }
00241
00242 static void sqlite_client_thread(void *arg)
00243 {
00244 unsigned long i, succeeded, failed;
00245 DBPool *pool = arg;
00246 char *errmsg = 0;
00247
00248 succeeded = failed = 0;
00249
00250 info(0,"Client thread started with %ld queries to perform on pool", queries);
00251
00252
00253 for (i = 1; i <= queries; i++) {
00254 DBPoolConn *pconn;
00255 int state;
00256
00257
00258 pconn = dbpool_conn_consume(pool);
00259 debug("",0,"Query %ld/%ld: sqlite conn obj at %p",
00260 i, queries, (void*) pconn->conn);
00261
00262 state = sqlite_exec(pconn->conn, octstr_get_cstr(sql), callback, 0, &errmsg);
00263 if (state != SQLITE_OK) {
00264 error(0, "SQLite: %s", errmsg);
00265 failed++;
00266 } else {
00267 succeeded++;
00268 }
00269
00270
00271 dbpool_conn_produce(pconn);
00272 }
00273 info(0, "This thread: %ld succeeded, %ld failed.", succeeded, failed);
00274 }
00275 #endif
00276
00277 #ifdef HAVE_SQLITE3
00278 #include <sqlite3.h>
00279
00280 static DBConf *sqlite3_create_conf(Octstr *db)
00281 {
00282 DBConf *conf;
00283 conf = gw_malloc(sizeof(DBConf));
00284 conf->sqlite3 = gw_malloc(sizeof(SQLite3Conf));
00285
00286 conf->sqlite3->file = octstr_duplicate(db);
00287
00288 return conf;
00289 }
00290
00291 static int callback3(void *not_used, int argc, char **argv, char **col_name)
00292 {
00293 int i;
00294
00295 for (i = 0; i < argc; i++) {
00296 debug("",0,"SQLite3: result: %s = %s", col_name[i], argv[i]);
00297 }
00298
00299 return 0;
00300 }
00301
00302 static void sqlite3_client_thread(void *arg)
00303 {
00304 unsigned long i, succeeded, failed;
00305 DBPool *pool = arg;
00306 char *errmsg = 0;
00307
00308 succeeded = failed = 0;
00309
00310 info(0,"Client thread started with %ld queries to perform on pool", queries);
00311
00312
00313 for (i = 1; i <= queries; i++) {
00314 DBPoolConn *pconn;
00315 int state;
00316
00317
00318 pconn = dbpool_conn_consume(pool);
00319 debug("",0,"Query %ld/%ld: sqlite conn obj at %p",
00320 i, queries, (void*) pconn->conn);
00321
00322 state = sqlite3_exec(pconn->conn, octstr_get_cstr(sql), callback3, 0, &errmsg);
00323 if (state != SQLITE_OK) {
00324 error(0, "SQLite3: %s", errmsg);
00325 failed++;
00326 } else {
00327 succeeded++;
00328 }
00329
00330
00331 dbpool_conn_produce(pconn);
00332 }
00333 info(0, "This thread: %ld succeeded, %ld failed.", succeeded, failed);
00334 }
00335 #endif
00336
00337 static void inc_dec_thread(void *arg)
00338 {
00339 DBPool *pool = arg;
00340 int ret;
00341
00342
00343 info(0,"Decreasing pool by half of size, which is %d connections", abs(pool_size/2));
00344 ret = dbpool_decrease(pool, abs(pool_size/2));
00345 debug("",0,"Decreased by %d connections", ret);
00346 debug("",0,"Connections within pool: %ld", dbpool_conn_count(pool));
00347
00348
00349 info(0,"Increasing pool again by %d connections", pool_size);
00350 ret = dbpool_increase(pool, pool_size);
00351 debug("",0,"Increased by %d connections", ret);
00352 debug("",0,"Connections within pool: %ld", dbpool_conn_count(pool));
00353 }
00354
00355 int main(int argc, char **argv)
00356 {
00357 DBPool *pool;
00358 DBConf *conf = NULL;
00359 unsigned int num_threads = 1;
00360 unsigned long i;
00361 int opt;
00362 time_t start = 0, end = 0;
00363 double run_time;
00364 Octstr *user, *pass, *db, *host, *db_type;
00365 int j, bail_out;
00366
00367 user = pass = db = host = db_type = NULL;
00368
00369 gwlib_init();
00370
00371 sql = octstr_imm("SHOW STATUS");
00372
00373 while ((opt = getopt(argc, argv, "v:h:u:p:d:s:q:t:S:T:")) != EOF) {
00374 switch (opt) {
00375 case 'v':
00376 log_set_output_level(atoi(optarg));
00377 break;
00378
00379 case 'h':
00380 host = octstr_create(optarg);
00381 break;
00382
00383 case 'u':
00384 user = octstr_create(optarg);
00385 break;
00386
00387 case 'p':
00388 pass = octstr_create(optarg);
00389 break;
00390
00391 case 'd':
00392 db = octstr_create(optarg);
00393 break;
00394
00395 case 'S':
00396 octstr_destroy(sql);
00397 sql = octstr_create(optarg);
00398 break;
00399
00400 case 's':
00401 pool_size = atoi(optarg);
00402 break;
00403
00404 case 'q':
00405 queries = atoi(optarg);
00406 break;
00407
00408 case 't':
00409 num_threads = atoi(optarg);
00410 break;
00411
00412 case 'T':
00413 db_type = octstr_create(optarg);
00414 break;
00415
00416 case '?':
00417 default:
00418 error(0, "Invalid option %c", opt);
00419 help();
00420 panic(0, "Stopping.");
00421 }
00422 }
00423
00424 if (!optind) {
00425 help();
00426 exit(0);
00427 }
00428
00429 if (!db_type) {
00430 info(0, "No database type given assuming MySQL.");
00431 }
00432 else if (octstr_case_compare(db_type, octstr_imm("mysql")) == 0) {
00433 info(0, "Do tests for mysql database.");
00434 database_type = DBPOOL_MYSQL;
00435 }
00436 else if (octstr_case_compare(db_type, octstr_imm("oracle")) == 0) {
00437 info(0, "Do tests for oracle database.");
00438 database_type = DBPOOL_ORACLE;
00439 }
00440 else if (octstr_case_compare(db_type, octstr_imm("sqlite")) == 0) {
00441 info(0, "Do tests for sqlite database.");
00442 database_type = DBPOOL_SQLITE;
00443 }
00444 else if (octstr_case_compare(db_type, octstr_imm("sqlite3")) == 0) {
00445 info(0, "Do tests for sqlite3 database.");
00446 database_type = DBPOOL_SQLITE3;
00447 }
00448 else {
00449 panic(0, "Unknown database type '%s'", octstr_get_cstr(db_type));
00450 }
00451
00452
00453 switch (database_type) {
00454 case DBPOOL_ORACLE:
00455 bail_out = (!user || !pass || !db) ? 1 : 0;
00456 break;
00457 case DBPOOL_SQLITE:
00458 case DBPOOL_SQLITE3:
00459 bail_out = (!db) ? 1 : 0;
00460 break;
00461 default:
00462 bail_out = (!host || !user || !pass || !db) ? 1 : 0;
00463 break;
00464 }
00465 if (bail_out) {
00466 help();
00467 panic(0, "Database connection details are not fully provided!");
00468 }
00469
00470 for (j = 0; j < 1; j++) {
00471
00472
00473 switch (database_type) {
00474 #ifdef HAVE_MYSQL
00475 case DBPOOL_MYSQL:
00476 conf = mysql_create_conf(user,pass,db,host);
00477 client_thread = mysql_client_thread;
00478 break;
00479 #endif
00480 #ifdef HAVE_ORACLE
00481 case DBPOOL_ORACLE:
00482 conf = oracle_create_conf(user, pass, db);
00483 client_thread = oracle_client_thread;
00484 break;
00485 #endif
00486 #ifdef HAVE_SQLITE
00487 case DBPOOL_SQLITE:
00488 conf = sqlite_create_conf(db);
00489 client_thread = sqlite_client_thread;
00490 break;
00491 #endif
00492 #ifdef HAVE_SQLITE3
00493 case DBPOOL_SQLITE3:
00494 conf = sqlite3_create_conf(db);
00495 client_thread = sqlite3_client_thread;
00496 break;
00497 #endif
00498 default:
00499 panic(0, "ooops ....");
00500 };
00501
00502
00503 info(0,"Creating database pool to `%s' with %d connections type '%s'.",
00504 (host ? octstr_get_cstr(host) : octstr_get_cstr(db)), pool_size, octstr_get_cstr(db_type));
00505 pool = dbpool_create(database_type, conf, pool_size);
00506 debug("",0,"Connections within pool: %ld", dbpool_conn_count(pool));
00507
00508 for (i = 0; i < num_threads; ++i) {
00509 if (gwthread_create(inc_dec_thread, pool) == -1)
00510 panic(0, "Could not create thread %ld", i);
00511 }
00512 gwthread_join_all();
00513
00514 info(0, "Connections within pool: %ld", dbpool_conn_count(pool));
00515 info(0, "Checked pool, %d connections still active and ok", dbpool_check(pool));
00516
00517
00518 info(0,"SQL query is `%s'", octstr_get_cstr(sql));
00519 time(&start);
00520 for (i = 0; i < num_threads; ++i) {
00521 #if 0
00522 if (gwthread_create(inc_dec_thread, pool) == -1)
00523 panic(0, "Couldnot create thread %ld", i);
00524 #endif
00525 if (gwthread_create(client_thread, pool) == -1)
00526 panic(0, "Couldnot create thread %ld", i);
00527 }
00528
00529 gwthread_join_all();
00530 time(&end);
00531
00532 run_time = difftime(end, start);
00533 info(0, "%ld requests in %.2f seconds, %.2f requests/s.",
00534 (queries * num_threads), run_time, (float) (queries * num_threads) / (run_time==0?1:run_time));
00535
00536
00537 debug("",0,"Connections within pool: %ld", dbpool_conn_count(pool));
00538 info(0,"Checked pool, %d connections still active and ok", dbpool_check(pool));
00539
00540 info(0,"Destroying pool");
00541 dbpool_destroy(pool);
00542
00543 }
00544
00545 octstr_destroy(sql);
00546 octstr_destroy(db_type);
00547 octstr_destroy(user);
00548 octstr_destroy(pass);
00549 octstr_destroy(db);
00550 octstr_destroy(host);
00551 gwlib_shutdown();
00552
00553 return 0;
00554 }
00555
00556
00557 #endif
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.