* fix ns_db gethandle -timeout to do a non-blocking timeout where timeout=0.
| 1 | /* |
| 2 | * The contents of this file are subject to the AOLserver Public License |
| 3 | * Version 1.1 (the "License"); you may not use this file except in |
| 4 | * compliance with the License. You may obtain a copy of the License at |
| 5 | * http://aolserver.com/. |
| 6 | * |
| 7 | * Software distributed under the License is distributed on an "AS IS" |
| 8 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See |
| 9 | * the License for the specific language governing rights and limitations |
| 10 | * under the License. |
| 11 | * |
| 12 | * The Original Code is AOLserver Code and related documentation |
| 13 | * distributed by AOL. |
| 14 | * |
| 15 | * The Initial Developer of the Original Code is America Online, |
| 16 | * Inc. Portions created by AOL are Copyright (C) 1999 America Online, |
| 17 | * Inc. All Rights Reserved. |
| 18 | * |
| 19 | * Alternatively, the contents of this file may be used under the terms |
| 20 | * of the GNU General Public License (the "GPL"), in which case the |
| 21 | * provisions of GPL are applicable instead of those above. If you wish |
| 22 | * to allow use of your version of this file only under the terms of the |
| 23 | * GPL and not to allow others to use your version of this file under the |
| 24 | * License, indicate your decision by deleting the provisions above and |
| 25 | * replace them with the notice and other provisions required by the GPL. |
| 26 | * If you do not delete the provisions above, a recipient may use your |
| 27 | * version of this file under either the License or the GPL. |
| 28 | */ |
| 29 | |
| 30 | |
| 31 | /* |
| 32 | * dbinit.c -- |
| 33 | * |
| 34 | * This file contains routines for creating and accessing |
| 35 | * pools of database handles. |
| 36 | */ |
| 37 | |
| 38 | static const char *RCSID = "@(#) $Header: /cvsroot-fuse/aolserver/aolserver/nsdb/dbinit.c,v 1.5 2004/02/05 17:50:53 dossy Exp $, compiled: " __DATE__ " " __TIME__; |
| 39 | |
| 40 | #include "db.h" |
| 41 | |
| 42 | /* |
| 43 | * The following structure defines a database pool. |
| 44 | */ |
| 45 | |
| 46 | struct Handle; |
| 47 | |
| 48 | typedef struct Pool { |
| 49 | char *name; |
| 50 | char *desc; |
| 51 | char *source; |
| 52 | char *user; |
| 53 | char *pass; |
| 54 | int type; |
| 55 | Ns_Mutex lock; |
| 56 | Ns_Cond waitCond; |
| 57 | Ns_Cond getCond; |
| 58 | char *driver; |
| 59 | struct DbDriver *driverPtr; |
| 60 | int waiting; |
| 61 | int nhandles; |
| 62 | struct Handle *firstPtr; |
| 63 | struct Handle *lastPtr; |
| 64 | int fVerbose; |
| 65 | int fVerboseError; |
| 66 | time_t maxidle; |
| 67 | time_t maxopen; |
| 68 | int stale_on_close; |
| 69 | } Pool; |
| 70 | |
| 71 | /* |
| 72 | * The following structure defines the internal |
| 73 | * state of a database handle. |
| 74 | */ |
| 75 | |
| 76 | typedef struct Handle { |
| 77 | char *driver; |
| 78 | char *datasource; |
| 79 | char *user; |
| 80 | char *password; |
| 81 | void *connection; |
| 82 | char *poolname; |
| 83 | int connected; |
| 84 | int verbose; |
| 85 | Ns_Set *row; |
| 86 | char cExceptionCode[6]; |
| 87 | Ns_DString dsExceptionMsg; |
| 88 | void *context; |
| 89 | void *statement; |
| 90 | int fetchingRows; |
| 91 | /* Members above must match Ns_DbHandle */ |
| 92 | struct Handle *nextPtr; |
| 93 | struct Pool *poolPtr; |
| 94 | time_t otime; |
| 95 | time_t atime; |
| 96 | int stale; |
| 97 | int stale_on_close; |
| 98 | } Handle; |
| 99 | |
| 100 | /* |
| 101 | * The following structure maintains per-server data. |
| 102 | */ |
| 103 | |
| 104 | typedef struct ServData { |
| 105 | char *defpool; |
| 106 | char *allowed; |
| 107 | } ServData; |
| 108 | |
| 109 | /* |
| 110 | * Local functions defined in this file |
| 111 | */ |
| 112 | |
| 113 | static Pool *<a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_GetPool">GetPool</a>(char *pool); |
| 114 | static void <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_ReturnHandle">ReturnHandle</a>(Handle * handle); |
| 115 | static int <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_IsStale">IsStale</a>(Handle *, time_t now); |
| 116 | static int <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Connect">Connect</a>(Handle *); |
| 117 | static Pool *<a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_CreatePool">CreatePool</a>(char *pool, char *path, char *driver); |
| 118 | static int <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_IncrCount">IncrCount</a>(Pool *poolPtr, int incr); |
| 119 | static ServData *<a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_GetServer">GetServer</a>(char *server); |
| 120 | static Ns_TlsCleanup <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_FreeTable">FreeTable</a>; |
| 121 | static Ns_Callback <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_CheckPool">CheckPool</a>; |
| 122 | static Ns_ArgProc <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_CheckArgProc">CheckArgProc</a>; |
| 123 | |
| 124 | /* |
| 125 | * Static variables defined in this file |
| 126 | */ |
| 127 | |
| 128 | static Tcl_HashTable poolsTable; |
| 129 | static Tcl_HashTable serversTable; |
| 130 | static Ns_Tls tls; |
| 131 | |
| 132 | |
| 133 | /* |
| 134 | *---------------------------------------------------------------------- |
| 135 | * |
| 136 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbPoolDescription">Ns_DbPoolDescription</a> -- |
| 137 | * |
| 138 | * Return the pool's description string. |
| 139 | * |
| 140 | * Results: |
| 141 | * Configured description string or NULL. |
| 142 | * |
| 143 | * Side effects: |
| 144 | * None. |
| 145 | * |
| 146 | *---------------------------------------------------------------------- |
| 147 | */ |
| 148 | |
| 149 | char * |
| 150 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbPoolDescription">Ns_DbPoolDescription</a>(char *pool) |
| 151 | { |
| 152 | Pool *poolPtr; |
| 153 | |
| 154 | poolPtr = <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_GetPool">GetPool</a>(pool); |
| 155 | if (poolPtr == NULL) { |
| 156 | return NULL; |
| 157 | } |
| 158 | return poolPtr->desc; |
| 159 | } |
| 160 | |
| 161 | |
| 162 | /* |
| 163 | *---------------------------------------------------------------------- |
| 164 | * |
| 165 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbPoolDefault">Ns_DbPoolDefault</a> -- |
| 166 | * |
| 167 | * Return the default pool. |
| 168 | * |
| 169 | * Results: |
| 170 | * String name of default pool or NULL if no default is defined. |
| 171 | * |
| 172 | * Side effects: |
| 173 | * None. |
| 174 | * |
| 175 | *---------------------------------------------------------------------- |
| 176 | */ |
| 177 | |
| 178 | char * |
| 179 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbPoolDefault">Ns_DbPoolDefault</a>(char *server) |
| 180 | { |
| 181 | ServData *sdataPtr = <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_GetServer">GetServer</a>(server); |
| 182 | |
| 183 | return (sdataPtr ? sdataPtr->defpool : NULL); |
| 184 | } |
| 185 | |
| 186 | |
| 187 | /* |
| 188 | *---------------------------------------------------------------------- |
| 189 | * |
| 190 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbPoolList">Ns_DbPoolList</a> -- |
| 191 | * |
| 192 | * Return the list of all pools. |
| 193 | * |
| 194 | * Results: |
| 195 | * Double-null terminated list of pool names. |
| 196 | * |
| 197 | * Side effects: |
| 198 | * None. |
| 199 | * |
| 200 | *---------------------------------------------------------------------- |
| 201 | */ |
| 202 | |
| 203 | char * |
| 204 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbPoolList">Ns_DbPoolList</a>(char *server) |
| 205 | { |
| 206 | ServData *sdataPtr = <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_GetServer">GetServer</a>(server); |
| 207 | |
| 208 | return (sdataPtr ? sdataPtr->allowed : NULL); |
| 209 | } |
| 210 | |
| 211 | |
| 212 | /* |
| 213 | *---------------------------------------------------------------------- |
| 214 | * |
| 215 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbPoolAllowable">Ns_DbPoolAllowable</a> -- |
| 216 | * |
| 217 | * Check that access is allowed to a pool. |
| 218 | * |
| 219 | * Results: |
| 220 | * NS_TRUE if allowed, NS_FALSE otherwise. |
| 221 | * |
| 222 | * Side effects: |
| 223 | * None. |
| 224 | * |
| 225 | *---------------------------------------------------------------------- |
| 226 | */ |
| 227 | |
| 228 | int |
| 229 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbPoolAllowable">Ns_DbPoolAllowable</a>(char *server, char *pool) |
| 230 | { |
| 231 | register char *p; |
| 232 | |
| 233 | p = <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbPoolList">Ns_DbPoolList</a>(server); |
| 234 | if (p != NULL) { |
| 235 | while (*p != '\0') { |
| 236 | if (STREQ(pool, p)) { |
| 237 | return NS_TRUE; |
| 238 | } |
| 239 | p = p + strlen(p) + 1; |
| 240 | } |
| 241 | } |
| 242 | return NS_FALSE; |
| 243 | } |
| 244 | |
| 245 | |
| 246 | /* |
| 247 | *---------------------------------------------------------------------- |
| 248 | * |
| 249 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbPoolPutHandle">Ns_DbPoolPutHandle</a> -- |
| 250 | * |
| 251 | * Cleanup and then return a handle to its pool. |
| 252 | * |
| 253 | * Results: |
| 254 | * None. |
| 255 | * |
| 256 | * Side effects: |
| 257 | * Handle is flushed, reset, and possibly closed as required. |
| 258 | * |
| 259 | *---------------------------------------------------------------------- |
| 260 | */ |
| 261 | |
| 262 | void |
| 263 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbPoolPutHandle">Ns_DbPoolPutHandle</a>(Ns_DbHandle *handle) |
| 264 | { |
| 265 | Handle *handlePtr; |
| 266 | Pool *poolPtr; |
| 267 | time_t now; |
| 268 | |
| 269 | handlePtr = (Handle *) handle; |
| 270 | poolPtr = handlePtr->poolPtr; |
| 271 | |
| 272 | /* |
| 273 | * Cleanup the handle. |
| 274 | */ |
| 275 | |
| 276 | <a href="/cvs/aolserver/aolserver/nsdb/dbdrv.c#A_Ns_DbFlush">Ns_DbFlush</a>(handle); |
| 277 | <a href="/cvs/aolserver/aolserver/nsdb/dbdrv.c#A_Ns_DbResetHandle">Ns_DbResetHandle</a>(handle); |
| 278 | |
| 279 | <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringFree">Ns_DStringFree</a>(&handle->dsExceptionMsg); |
| 280 | handle->cExceptionCode[0] = '\0'; |
| 281 | |
| 282 | /* |
| 283 | * Close the handle if it's stale, otherwise update |
| 284 | * the last access time. |
| 285 | */ |
| 286 | |
| 287 | time(&now); |
| 288 | if (<a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_IsStale">IsStale</a>(handlePtr, now)) { |
| 289 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_NsDbDisconnect">NsDbDisconnect</a>(handle); |
| 290 | } else { |
| 291 | handlePtr->atime = now; |
| 292 | } |
| 293 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_IncrCount">IncrCount</a>(poolPtr, -1); |
| 294 | Ns_MutexLock(&poolPtr->lock); |
| 295 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_ReturnHandle">ReturnHandle</a>(handlePtr); |
| 296 | if (poolPtr->waiting) { |
| 297 | Ns_CondSignal(&poolPtr->getCond); |
| 298 | } |
| 299 | Ns_MutexUnlock(&poolPtr->lock); |
| 300 | } |
| 301 | |
| 302 | |
| 303 | /* |
| 304 | *---------------------------------------------------------------------- |
| 305 | * |
| 306 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbPoolTimedGetHandle">Ns_DbPoolTimedGetHandle</a> -- |
| 307 | * |
| 308 | * Return a single handle from a pool within the given number of |
| 309 | * seconds. |
| 310 | * |
| 311 | * Results: |
| 312 | * Pointer to Ns_DbHandle or NULL on error or timeout. |
| 313 | * |
| 314 | * Side effects: |
| 315 | * Database may be opened if needed. |
| 316 | * |
| 317 | *---------------------------------------------------------------------- |
| 318 | */ |
| 319 | |
| 320 | Ns_DbHandle * |
| 321 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbPoolTimedGetHandle">Ns_DbPoolTimedGetHandle</a>(char *pool, int wait) |
| 322 | { |
| 323 | Ns_DbHandle *handle; |
| 324 | |
| 325 | if (<a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbPoolTimedGetMultipleHandles">Ns_DbPoolTimedGetMultipleHandles</a>(&handle, pool, 1, wait) != NS_OK) { |
| 326 | return NULL; |
| 327 | } |
| 328 | return handle; |
| 329 | } |
| 330 | |
| 331 | |
| 332 | /* |
| 333 | *---------------------------------------------------------------------- |
| 334 | * |
| 335 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbPoolGetHandle">Ns_DbPoolGetHandle</a> -- |
| 336 | * |
| 337 | * Return a single handle from a pool. |
| 338 | * |
| 339 | * Results: |
| 340 | * Pointer to Ns_DbHandle or NULL on error. |
| 341 | * |
| 342 | * Side effects: |
| 343 | * Database may be opened if needed. |
| 344 | * |
| 345 | *---------------------------------------------------------------------- |
| 346 | */ |
| 347 | |
| 348 | Ns_DbHandle * |
| 349 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbPoolGetHandle">Ns_DbPoolGetHandle</a>(char *pool) |
| 350 | { |
| 351 | return <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbPoolTimedGetHandle">Ns_DbPoolTimedGetHandle</a>(pool, 0); |
| 352 | } |
| 353 | |
| 354 | |
| 355 | /* |
| 356 | *---------------------------------------------------------------------- |
| 357 | * |
| 358 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbPoolGetMultipleHandles">Ns_DbPoolGetMultipleHandles</a> -- |
| 359 | * |
| 360 | * Return 1 or more handles from a pool. |
| 361 | * |
| 362 | * Results: |
| 363 | * NS_OK if handles were allocated, NS_ERROR otherwise. |
| 364 | * |
| 365 | * Side effects: |
| 366 | * Given array of handles is updated with pointers to allocated |
| 367 | * handles. Also, database may be opened if needed. |
| 368 | * |
| 369 | *---------------------------------------------------------------------- |
| 370 | */ |
| 371 | |
| 372 | int |
| 373 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbPoolGetMultipleHandles">Ns_DbPoolGetMultipleHandles</a>(Ns_DbHandle **handles, char *pool, int nwant) |
| 374 | { |
| 375 | return <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbPoolTimedGetMultipleHandles">Ns_DbPoolTimedGetMultipleHandles</a>(handles, pool, nwant, 0); |
| 376 | } |
| 377 | |
| 378 | |
| 379 | /* |
| 380 | *---------------------------------------------------------------------- |
| 381 | * |
| 382 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbPoolTimedGetMultipleHandles">Ns_DbPoolTimedGetMultipleHandles</a> -- |
| 383 | * |
| 384 | * Return 1 or more handles from a pool within the given number |
| 385 | * of seconds. |
| 386 | * |
| 387 | * Results: |
| 388 | * NS_OK if the handlers where allocated, NS_TIMEOUT if the |
| 389 | * thread could not wait long enough for the handles, NS_ERROR |
| 390 | * otherwise. |
| 391 | * |
| 392 | * Side effects: |
| 393 | * Given array of handles is updated with pointers to allocated |
| 394 | * handles. Also, database may be opened if needed. |
| 395 | * |
| 396 | *---------------------------------------------------------------------- |
| 397 | */ |
| 398 | |
| 399 | int |
| 400 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbPoolTimedGetMultipleHandles">Ns_DbPoolTimedGetMultipleHandles</a>(Ns_DbHandle **handles, char *pool, |
| 401 | int nwant, int wait) |
| 402 | { |
| 403 | Handle *handlePtr; |
| 404 | Handle **handlesPtrPtr = (Handle **) handles; |
| 405 | Pool *poolPtr; |
| 406 | Ns_Time timeout, *timePtr; |
| 407 | int i, ngot, status; |
| 408 | |
| 409 | /* |
| 410 | * Verify the pool, the number of available handles in the pool, |
| 411 | * and that the calling thread does not already own handles from |
| 412 | * this pool. |
| 413 | */ |
| 414 | |
| 415 | poolPtr = <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_GetPool">GetPool</a>(pool); |
| 416 | if (poolPtr == NULL) { |
| 417 | <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Error, "dbinit: no such pool '%s'", pool); |
| 418 | return NS_ERROR; |
| 419 | } |
| 420 | if (poolPtr->nhandles < nwant) { |
| 421 | <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Error, "dbinit: " |
| 422 | "failed to get %d handles from a db pool of only %d handles: '%s'", |
| 423 | nwant, poolPtr->nhandles, pool); |
| 424 | return NS_ERROR; |
| 425 | } |
| 426 | ngot = <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_IncrCount">IncrCount</a>(poolPtr, nwant); |
| 427 | if (ngot > 0) { |
| 428 | <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Error, "dbinit: db handle limit exceeded: " |
| 429 | "thread already owns %d handle%s from pool '%s'", |
| 430 | ngot, ngot == 1 ? "" : "s", pool); |
| 431 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_IncrCount">IncrCount</a>(poolPtr, -nwant); |
| 432 | return NS_ERROR; |
| 433 | } |
| 434 | |
| 435 | /* |
| 436 | * Wait until this thread can be the exclusive thread aquireing |
| 437 | * handles and then wait until all requested handles are available, |
| 438 | * watching for timeout in either of these waits. |
| 439 | */ |
| 440 | |
| 441 | if (wait < 0) { |
| 442 | timePtr = NULL; |
| 443 | } else { |
| 444 | Ns_GetTime(&timeout); |
| 445 | Ns_IncrTime(&timeout, wait, 0); |
| 446 | timePtr = &timeout; |
| 447 | } |
| 448 | status = NS_OK; |
| 449 | Ns_MutexLock(&poolPtr->lock); |
| 450 | while (status == NS_OK && poolPtr->waiting) { |
| 451 | status = Ns_CondTimedWait(&poolPtr->waitCond, &poolPtr->lock, timePtr); |
| 452 | } |
| 453 | if (status == NS_OK) { |
| 454 | poolPtr->waiting = 1; |
| 455 | while (status == NS_OK && ngot < nwant) { |
| 456 | while (status == NS_OK && poolPtr->firstPtr == NULL) { |
| 457 | status = Ns_CondTimedWait(&poolPtr->getCond, &poolPtr->lock, |
| 458 | timePtr); |
| 459 | } |
| 460 | if (poolPtr->firstPtr != NULL) { |
| 461 | handlePtr = poolPtr->firstPtr; |
| 462 | poolPtr->firstPtr = handlePtr->nextPtr; |
| 463 | handlePtr->nextPtr = NULL; |
| 464 | if (poolPtr->lastPtr == handlePtr) { |
| 465 | poolPtr->lastPtr = NULL; |
| 466 | } |
| 467 | handlesPtrPtr[ngot++] = handlePtr; |
| 468 | } |
| 469 | } |
| 470 | poolPtr->waiting = 0; |
| 471 | Ns_CondSignal(&poolPtr->waitCond); |
| 472 | } |
| 473 | Ns_MutexUnlock(&poolPtr->lock); |
| 474 | |
| 475 | /* |
| 476 | * Handle special race condition where the final requested handle |
| 477 | * arrived just as the condition wait was timing out. |
| 478 | */ |
| 479 | |
| 480 | if (status == NS_TIMEOUT && ngot == nwant) { |
| 481 | status = NS_OK; |
| 482 | } |
| 483 | |
| 484 | /* |
| 485 | * If status is still ok, connect any handles not already connected, |
| 486 | * otherwise return any allocated handles back to the pool, then |
| 487 | * update the final number of handles owned by this thread. |
| 488 | */ |
| 489 | |
| 490 | for (i = 0; status == NS_OK && i < ngot; ++i) { |
| 491 | handlePtr = handlesPtrPtr[i]; |
| 492 | if (handlePtr->connected == NS_FALSE) { |
| 493 | status = <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Connect">Connect</a>(handlePtr); |
| 494 | } |
| 495 | } |
| 496 | if (status != NS_OK) { |
| 497 | Ns_MutexLock(&poolPtr->lock); |
| 498 | while (ngot > 0) { |
| 499 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_ReturnHandle">ReturnHandle</a>(handlesPtrPtr[--ngot]); |
| 500 | } |
| 501 | if (poolPtr->waiting) { |
| 502 | Ns_CondSignal(&poolPtr->getCond); |
| 503 | } |
| 504 | Ns_MutexUnlock(&poolPtr->lock); |
| 505 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_IncrCount">IncrCount</a>(poolPtr, -nwant); |
| 506 | } |
| 507 | return status; |
| 508 | } |
| 509 | |
| 510 | |
| 511 | /* |
| 512 | *---------------------------------------------------------------------- |
| 513 | * |
| 514 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbBouncePool">Ns_DbBouncePool</a> -- |
| 515 | * |
| 516 | * Close all handles in the pool. |
| 517 | * |
| 518 | * Results: |
| 519 | * NS_OK if pool was bounce, NS_ERROR otherwise. |
| 520 | * |
| 521 | * Side effects: |
| 522 | * Handles are all marked stale and then closed by <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_CheckPool">CheckPool</a>. |
| 523 | * |
| 524 | *---------------------------------------------------------------------- |
| 525 | */ |
| 526 | |
| 527 | int |
| 528 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Ns_DbBouncePool">Ns_DbBouncePool</a>(char *pool) |
| 529 | { |
| 530 | Pool *poolPtr; |
| 531 | Handle *handlePtr; |
| 532 | |
| 533 | poolPtr = <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_GetPool">GetPool</a>(pool); |
| 534 | if (poolPtr == NULL) { |
| 535 | return NS_ERROR; |
| 536 | } |
| 537 | Ns_MutexLock(&poolPtr->lock); |
| 538 | poolPtr->stale_on_close++; |
| 539 | handlePtr = poolPtr->firstPtr; |
| 540 | while (handlePtr != NULL) { |
| 541 | if (handlePtr->connected) { |
| 542 | handlePtr->stale = 1; |
| 543 | } |
| 544 | handlePtr->stale_on_close = poolPtr->stale_on_close; |
| 545 | handlePtr = handlePtr->nextPtr; |
| 546 | } |
| 547 | Ns_MutexUnlock(&poolPtr->lock); |
| 548 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_CheckPool">CheckPool</a>(poolPtr); |
| 549 | |
| 550 | return NS_OK; |
| 551 | } |
| 552 | |
| 553 | |
| 554 | /* |
| 555 | *---------------------------------------------------------------------- |
| 556 | * |
| 557 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_NsDbInitPools">NsDbInitPools</a> -- |
| 558 | * |
| 559 | * Initialize the database pools at startup. |
| 560 | * |
| 561 | * Results: |
| 562 | * None. |
| 563 | * |
| 564 | * Side effects: |
| 565 | * Pools may be created as configured. |
| 566 | * |
| 567 | *---------------------------------------------------------------------- |
| 568 | */ |
| 569 | |
| 570 | void |
| 571 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_NsDbInitPools">NsDbInitPools</a>(void) |
| 572 | { |
| 573 | Tcl_HashEntry *hPtr; |
| 574 | Pool *poolPtr; |
| 575 | Ns_Set *pools; |
| 576 | char *path, *pool, *driver; |
| 577 | int new, i; |
| 578 | |
| 579 | Ns_TlsAlloc(&tls, <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_FreeTable">FreeTable</a>); |
| 580 | |
| 581 | /* |
| 582 | * Attempt to create each database pool. |
| 583 | */ |
| 584 | |
| 585 | Tcl_InitHashTable(&serversTable, TCL_STRING_KEYS); |
| 586 | Tcl_InitHashTable(&poolsTable, TCL_STRING_KEYS); |
| 587 | pools = <a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetSection">Ns_ConfigGetSection</a>("ns/db/pools"); |
| 588 | for (i = 0; pools != NULL && i < Ns_SetSize(pools); ++i) { |
| 589 | pool = Ns_SetKey(pools, i); |
| 590 | hPtr = Tcl_CreateHashEntry(&poolsTable, pool, &new); |
| 591 | if (!new) { |
| 592 | <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Error, "dbinit: duplicate pool: %s", pool); |
| 593 | continue; |
| 594 | } |
| 595 | path = <a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetPath">Ns_ConfigGetPath</a>(NULL, NULL, "db", "pool", pool, NULL); |
| 596 | driver = <a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetValue">Ns_ConfigGetValue</a>(path, "driver"); |
| 597 | poolPtr = <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_CreatePool">CreatePool</a>(pool, path, driver); |
| 598 | if (poolPtr == NULL) { |
| 599 | Tcl_DeleteHashEntry(hPtr); |
| 600 | } else { |
| 601 | Tcl_SetHashValue(hPtr, poolPtr); |
| 602 | } |
| 603 | } |
| 604 | <a href="/cvs/aolserver/aolserver/nsd/proc.c#A_Ns_RegisterProcInfo">Ns_RegisterProcInfo</a>(<a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_CheckPool">CheckPool</a>, "nsdb:check", <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_CheckArgProc">CheckArgProc</a>); |
| 605 | } |
| 606 | |
| 607 | |
| 608 | /* |
| 609 | *---------------------------------------------------------------------- |
| 610 | * |
| 611 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_NsDbInitServer">NsDbInitServer</a> -- |
| 612 | * |
| 613 | * Initialize a virtual server allowed and default options. |
| 614 | * |
| 615 | * Results: |
| 616 | * None. |
| 617 | * |
| 618 | * Side effects: |
| 619 | * None. |
| 620 | * |
| 621 | *---------------------------------------------------------------------- |
| 622 | */ |
| 623 | |
| 624 | void |
| 625 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_NsDbInitServer">NsDbInitServer</a>(char *server) |
| 626 | { |
| 627 | Pool *poolPtr; |
| 628 | ServData *sdataPtr; |
| 629 | Tcl_HashEntry *hPtr; |
| 630 | Tcl_HashSearch search; |
| 631 | char *path, *pool, *p; |
| 632 | Ns_DString ds; |
| 633 | int new; |
| 634 | |
| 635 | path = <a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetPath">Ns_ConfigGetPath</a>(server, NULL, "db", NULL); |
| 636 | |
| 637 | /* |
| 638 | * Verify the default pool exists, if any. |
| 639 | */ |
| 640 | |
| 641 | sdataPtr = ns_malloc(sizeof(ServData)); |
| 642 | hPtr = Tcl_CreateHashEntry(&serversTable, server, &new); |
| 643 | Tcl_SetHashValue(hPtr, sdataPtr); |
| 644 | sdataPtr->defpool = <a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetValue">Ns_ConfigGetValue</a>(path, "defaultpool"); |
| 645 | if (sdataPtr->defpool != NULL && |
| 646 | (Tcl_FindHashEntry(&poolsTable, sdataPtr->defpool) == NULL)) { |
| 647 | <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Error, "dbinit: no such default pool '%s'", sdataPtr->defpool); |
| 648 | sdataPtr->defpool = NULL; |
| 649 | } |
| 650 | |
| 651 | /* |
| 652 | * Construct the allowed list and call the server-specific init. |
| 653 | */ |
| 654 | |
| 655 | sdataPtr->allowed = ""; |
| 656 | pool = <a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetValue">Ns_ConfigGetValue</a>(path, "pools"); |
| 657 | if (pool != NULL && poolsTable.numEntries > 0) { |
| 658 | <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringInit">Ns_DStringInit</a>(&ds); |
| 659 | if (STREQ(pool, "*")) { |
| 660 | hPtr = Tcl_FirstHashEntry(&poolsTable, &search); |
| 661 | while (hPtr != NULL) { |
| 662 | poolPtr = Tcl_GetHashValue(hPtr); |
| 663 | <a href="/cvs/aolserver/aolserver/nsdb/dbdrv.c#A_NsDbDriverInit">NsDbDriverInit</a>(server, poolPtr->driverPtr); |
| 664 | <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppendArg">Ns_DStringAppendArg</a>(&ds, poolPtr->name); |
| 665 | hPtr = Tcl_NextHashEntry(&search); |
| 666 | } |
| 667 | } else { |
| 668 | p = pool; |
| 669 | while (p != NULL && *p != '\0') { |
| 670 | p = strchr(pool, ','); |
| 671 | if (p != NULL) { |
| 672 | *p = '\0'; |
| 673 | } |
| 674 | hPtr = Tcl_FindHashEntry(&poolsTable, pool); |
| 675 | if (hPtr != NULL) { |
| 676 | poolPtr = Tcl_GetHashValue(hPtr); |
| 677 | <a href="/cvs/aolserver/aolserver/nsdb/dbdrv.c#A_NsDbDriverInit">NsDbDriverInit</a>(server, poolPtr->driverPtr); |
| 678 | <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppendArg">Ns_DStringAppendArg</a>(&ds, poolPtr->name); |
| 679 | } |
| 680 | if (p != NULL) { |
| 681 | *p++ = ','; |
| 682 | } |
| 683 | pool = p; |
| 684 | } |
| 685 | } |
| 686 | sdataPtr->allowed = ns_malloc((size_t)(ds.length + 1)); |
| 687 | memcpy(sdataPtr->allowed, ds.string, (size_t)(ds.length + 1)); |
| 688 | <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringFree">Ns_DStringFree</a>(&ds); |
| 689 | } |
| 690 | } |
| 691 | |
| 692 | |
| 693 | /* |
| 694 | *---------------------------------------------------------------------- |
| 695 | * |
| 696 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_NsDbDisconnect">NsDbDisconnect</a> -- |
| 697 | * |
| 698 | * Disconnect a handle by closing the database if needed. |
| 699 | * |
| 700 | * Results: |
| 701 | * None. |
| 702 | * |
| 703 | * Side effects: |
| 704 | * None. |
| 705 | * |
| 706 | *---------------------------------------------------------------------- |
| 707 | */ |
| 708 | |
| 709 | void |
| 710 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_NsDbDisconnect">NsDbDisconnect</a>(Ns_DbHandle *handle) |
| 711 | { |
| 712 | Handle *handlePtr = (Handle *) handle; |
| 713 | |
| 714 | <a href="/cvs/aolserver/aolserver/nsdb/dbdrv.c#A_NsDbClose">NsDbClose</a>(handle); |
| 715 | handlePtr->connected = NS_FALSE; |
| 716 | handlePtr->atime = handlePtr->otime = 0; |
| 717 | handlePtr->stale = NS_FALSE; |
| 718 | } |
| 719 | |
| 720 | |
| 721 | /* |
| 722 | *---------------------------------------------------------------------- |
| 723 | * |
| 724 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_NsDbLogSql">NsDbLogSql</a> -- |
| 725 | * |
| 726 | * <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> a SQL statement depending on the verbose state of the |
| 727 | * handle. |
| 728 | * |
| 729 | * Results: |
| 730 | * None. |
| 731 | * |
| 732 | * Side effects: |
| 733 | * None. |
| 734 | * |
| 735 | *---------------------------------------------------------------------- |
| 736 | */ |
| 737 | |
| 738 | void |
| 739 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_NsDbLogSql">NsDbLogSql</a>(Ns_DbHandle *handle, char *sql) |
| 740 | { |
| 741 | Handle *handlePtr = (Handle *) handle; |
| 742 | |
| 743 | if (handle->dsExceptionMsg.length > 0) { |
| 744 | if (handlePtr->poolPtr->fVerboseError || handle->verbose) { |
| 745 | |
| 746 | <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Error, "dbinit: error(%s,%s): '%s'", |
| 747 | handle->datasource, handle->dsExceptionMsg.string, sql); |
| 748 | } |
| 749 | } else if (handle->verbose) { |
| 750 | <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Notice, "dbinit: sql(%s): '%s'", handle->datasource, sql); |
| 751 | } |
| 752 | } |
| 753 | |
| 754 | |
| 755 | /* |
| 756 | *---------------------------------------------------------------------- |
| 757 | * |
| 758 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_NsDbGetDriver">NsDbGetDriver</a> -- |
| 759 | * |
| 760 | * Return a pointer to the driver structure for a handle. |
| 761 | * |
| 762 | * Results: |
| 763 | * Pointer to driver or NULL on error. |
| 764 | * |
| 765 | * Side effects: |
| 766 | * None. |
| 767 | * |
| 768 | *---------------------------------------------------------------------- |
| 769 | */ |
| 770 | |
| 771 | struct DbDriver * |
| 772 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_NsDbGetDriver">NsDbGetDriver</a>(Ns_DbHandle *handle) |
| 773 | { |
| 774 | Handle *handlePtr = (Handle *) handle; |
| 775 | |
| 776 | if (handlePtr != NULL && handlePtr->poolPtr != NULL) { |
| 777 | return handlePtr->poolPtr->driverPtr; |
| 778 | } |
| 779 | |
| 780 | return NULL; |
| 781 | } |
| 782 | |
| 783 | |
| 784 | /* |
| 785 | *---------------------------------------------------------------------- |
| 786 | * |
| 787 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_GetPool">GetPool</a> -- |
| 788 | * |
| 789 | * Return the Pool structure for the given pool name. |
| 790 | * |
| 791 | * Results: |
| 792 | * Pointer to Pool structure or NULL if pool does not exist. |
| 793 | * |
| 794 | * Side effects: |
| 795 | * None. |
| 796 | * |
| 797 | *---------------------------------------------------------------------- |
| 798 | */ |
| 799 | |
| 800 | static Pool * |
| 801 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_GetPool">GetPool</a>(char *pool) |
| 802 | { |
| 803 | Tcl_HashEntry *hPtr; |
| 804 | |
| 805 | hPtr = Tcl_FindHashEntry(&poolsTable, pool); |
| 806 | if (hPtr == NULL) { |
| 807 | return NULL; |
| 808 | } |
| 809 | |
| 810 | return (Pool *) Tcl_GetHashValue(hPtr); |
| 811 | } |
| 812 | |
| 813 | |
| 814 | /* |
| 815 | *---------------------------------------------------------------------- |
| 816 | * |
| 817 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_ReturnHandle">ReturnHandle</a> -- |
| 818 | * |
| 819 | * Return a handle to its pool. Connected handles are pushed on |
| 820 | * the front of the list, disconnected handles are appened to |
| 821 | * the end. |
| 822 | * |
| 823 | * Results: |
| 824 | * None. |
| 825 | * |
| 826 | * Side effects: |
| 827 | * Handle is returned to the pool. Note: The pool lock must be |
| 828 | * held by the caller and this function does not signal a thread |
| 829 | * waiting for handles. |
| 830 | * |
| 831 | *---------------------------------------------------------------------- |
| 832 | */ |
| 833 | |
| 834 | static void |
| 835 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_ReturnHandle">ReturnHandle</a>(Handle *handlePtr) |
| 836 | { |
| 837 | Pool *poolPtr; |
| 838 | |
| 839 | poolPtr = handlePtr->poolPtr; |
| 840 | if (poolPtr->firstPtr == NULL) { |
| 841 | poolPtr->firstPtr = poolPtr->lastPtr = handlePtr; |
| 842 | handlePtr->nextPtr = NULL; |
| 843 | } else if (handlePtr->connected) { |
| 844 | handlePtr->nextPtr = poolPtr->firstPtr; |
| 845 | poolPtr->firstPtr = handlePtr; |
| 846 | } else { |
| 847 | poolPtr->lastPtr->nextPtr = handlePtr; |
| 848 | poolPtr->lastPtr = handlePtr; |
| 849 | handlePtr->nextPtr = NULL; |
| 850 | } |
| 851 | } |
| 852 | |
| 853 | |
| 854 | /* |
| 855 | *---------------------------------------------------------------------- |
| 856 | * |
| 857 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_IsStale">IsStale</a> -- |
| 858 | * |
| 859 | * Check to see if a handle is stale. |
| 860 | * |
| 861 | * Results: |
| 862 | * NS_TRUE if handle stale, NS_FALSE otherwise. |
| 863 | * |
| 864 | * Side effects: |
| 865 | * None. |
| 866 | * |
| 867 | *---------------------------------------------------------------------- |
| 868 | */ |
| 869 | |
| 870 | static int |
| 871 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_IsStale">IsStale</a>(Handle *handlePtr, time_t now) |
| 872 | { |
| 873 | time_t minAccess, minOpen; |
| 874 | |
| 875 | if (handlePtr->connected) { |
| 876 | minAccess = now - handlePtr->poolPtr->maxidle; |
| 877 | minOpen = now - handlePtr->poolPtr->maxopen; |
| 878 | if ((handlePtr->poolPtr->maxidle && handlePtr->atime < minAccess) || |
| 879 | (handlePtr->poolPtr->maxopen && (handlePtr->otime < minOpen)) || |
| 880 | (handlePtr->stale == NS_TRUE) || |
| 881 | (handlePtr->poolPtr->stale_on_close > handlePtr->stale_on_close)) { |
| 882 | |
| 883 | if (handlePtr->poolPtr->fVerbose) { |
| 884 | <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Notice, "dbinit: closing %s handle in pool '%s'", |
| 885 | handlePtr->atime < minAccess ? "idle" : "old", |
| 886 | handlePtr->poolname); |
| 887 | } |
| 888 | return NS_TRUE; |
| 889 | } |
| 890 | } |
| 891 | |
| 892 | return NS_FALSE; |
| 893 | } |
| 894 | |
| 895 | |
| 896 | /* |
| 897 | *---------------------------------------------------------------------- |
| 898 | * |
| 899 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_CheckArgProc">CheckArgProc</a> -- |
| 900 | * |
| 901 | * Ns_ArgProc callback for the pool checker. |
| 902 | * |
| 903 | * Results: |
| 904 | * None. |
| 905 | * |
| 906 | * Side effects: |
| 907 | * Copies name of pool to given dstring. |
| 908 | * |
| 909 | *---------------------------------------------------------------------- |
| 910 | */ |
| 911 | |
| 912 | static void |
| 913 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_CheckArgProc">CheckArgProc</a>(Tcl_DString *dsPtr, void *arg) |
| 914 | { |
| 915 | Pool *poolPtr = arg; |
| 916 | |
| 917 | Tcl_DStringAppendElement(dsPtr, poolPtr->name); |
| 918 | } |
| 919 | |
| 920 | |
| 921 | /* |
| 922 | *---------------------------------------------------------------------- |
| 923 | * |
| 924 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_CheckPool">CheckPool</a> -- |
| 925 | * |
| 926 | * Verify all handles in a pool are not stale. |
| 927 | * |
| 928 | * Results: |
| 929 | * None. |
| 930 | * |
| 931 | * Side effects: |
| 932 | * Stale handles, if any, are closed. |
| 933 | * |
| 934 | *---------------------------------------------------------------------- |
| 935 | */ |
| 936 | |
| 937 | static void |
| 938 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_CheckPool">CheckPool</a>(void *arg) |
| 939 | { |
| 940 | Pool *poolPtr = arg; |
| 941 | Handle *handlePtr, *nextPtr; |
| 942 | Handle *checkedPtr; |
| 943 | time_t now; |
| 944 | |
| 945 | time(&now); |
| 946 | checkedPtr = NULL; |
| 947 | |
| 948 | /* |
| 949 | * Grab the entire list of handles from the pool. |
| 950 | */ |
| 951 | |
| 952 | Ns_MutexLock(&poolPtr->lock); |
| 953 | handlePtr = poolPtr->firstPtr; |
| 954 | poolPtr->firstPtr = poolPtr->lastPtr = NULL; |
| 955 | Ns_MutexUnlock(&poolPtr->lock); |
| 956 | |
| 957 | /* |
| 958 | * Run through the list of handles, closing any |
| 959 | * which have gone stale, and then return them |
| 960 | * all to the pool. |
| 961 | */ |
| 962 | |
| 963 | if (handlePtr != NULL) { |
| 964 | while (handlePtr != NULL) { |
| 965 | nextPtr = handlePtr->nextPtr; |
| 966 | if (<a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_IsStale">IsStale</a>(handlePtr, now)) { |
| 967 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_NsDbDisconnect">NsDbDisconnect</a>((Ns_DbHandle *) handlePtr); |
| 968 | } |
| 969 | handlePtr->nextPtr = checkedPtr; |
| 970 | checkedPtr = handlePtr; |
| 971 | handlePtr = nextPtr; |
| 972 | } |
| 973 | |
| 974 | Ns_MutexLock(&poolPtr->lock); |
| 975 | handlePtr = checkedPtr; |
| 976 | while (handlePtr != NULL) { |
| 977 | nextPtr = handlePtr->nextPtr; |
| 978 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_ReturnHandle">ReturnHandle</a>(handlePtr); |
| 979 | handlePtr = nextPtr; |
| 980 | } |
| 981 | if (poolPtr->waiting) { |
| 982 | Ns_CondSignal(&poolPtr->getCond); |
| 983 | } |
| 984 | Ns_MutexUnlock(&poolPtr->lock); |
| 985 | } |
| 986 | } |
| 987 | |
| 988 | |
| 989 | /* |
| 990 | *---------------------------------------------------------------------- |
| 991 | * |
| 992 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_CreatePool">CreatePool</a> -- |
| 993 | * |
| 994 | * Create a new pool using the given driver. |
| 995 | * |
| 996 | * Results: |
| 997 | * Pointer to newly allocated Pool structure. |
| 998 | * |
| 999 | * Side effects: |
| 1000 | * None. |
| 1001 | * |
| 1002 | *---------------------------------------------------------------------- |
| 1003 | */ |
| 1004 | |
| 1005 | static Pool * |
| 1006 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_CreatePool">CreatePool</a>(char *pool, char *path, char *driver) |
| 1007 | { |
| 1008 | Pool *poolPtr; |
| 1009 | Handle *handlePtr; |
| 1010 | struct DbDriver *driverPtr; |
| 1011 | int i; |
| 1012 | char *source; |
| 1013 | |
| 1014 | if (driver == NULL) { |
| 1015 | <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Error, "dbinit: no driver for pool '%s'", pool); |
| 1016 | return NULL; |
| 1017 | } |
| 1018 | driverPtr = <a href="/cvs/aolserver/aolserver/nsdb/dbdrv.c#A_NsDbLoadDriver">NsDbLoadDriver</a>(driver); |
| 1019 | if (driverPtr == NULL) { |
| 1020 | return NULL; |
| 1021 | } |
| 1022 | source = <a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetValue">Ns_ConfigGetValue</a>(path, "datasource"); |
| 1023 | if (source == NULL) { |
| 1024 | <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Error, "dbinit: missing datasource for pool '%s'", pool); |
| 1025 | return NULL; |
| 1026 | } |
| 1027 | poolPtr = ns_malloc(sizeof(Pool)); |
| 1028 | poolPtr->driver = driver; |
| 1029 | poolPtr->driverPtr = driverPtr; |
| 1030 | Ns_MutexInit(&poolPtr->lock); |
| 1031 | Ns_MutexSetName2(&poolPtr->lock, "nsdb", pool); |
| 1032 | Ns_CondInit(&poolPtr->waitCond); |
| 1033 | Ns_CondInit(&poolPtr->getCond); |
| 1034 | poolPtr->source = source; |
| 1035 | poolPtr->name = pool; |
| 1036 | poolPtr->waiting = 0; |
| 1037 | poolPtr->user = <a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetValue">Ns_ConfigGetValue</a>(path, "user"); |
| 1038 | poolPtr->pass = <a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetValue">Ns_ConfigGetValue</a>(path, "password"); |
| 1039 | poolPtr->desc = <a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetValue">Ns_ConfigGetValue</a>("ns/db/pools", pool); |
| 1040 | poolPtr->stale_on_close = 0; |
| 1041 | if (!<a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetBool">Ns_ConfigGetBool</a>(path, "verbose", &poolPtr->fVerbose)) { |
| 1042 | poolPtr->fVerbose = 0; |
| 1043 | } |
| 1044 | if (!<a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetBool">Ns_ConfigGetBool</a>(path, "logsqlerrors", &poolPtr->fVerboseError)) { |
| 1045 | poolPtr->fVerboseError = 0; |
| 1046 | } |
| 1047 | if (!<a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetInt">Ns_ConfigGetInt</a>(path, "connections", &poolPtr->nhandles) |
| 1048 | || poolPtr->nhandles <= 0) { |
| 1049 | poolPtr->nhandles = 2; |
| 1050 | } |
| 1051 | if (<a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetInt">Ns_ConfigGetInt</a>(path, "MaxIdle", &i) == NS_FALSE || i < 0) { |
| 1052 | i = 600; /* 10 minutes */ |
| 1053 | } |
| 1054 | poolPtr->maxidle = i; |
| 1055 | if (<a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetInt">Ns_ConfigGetInt</a>(path, "MaxOpen", &i) == NS_FALSE || i < 0) { |
| 1056 | i = 3600; /* 1 hour */ |
| 1057 | } |
| 1058 | poolPtr->maxopen = i; |
| 1059 | poolPtr->firstPtr = poolPtr->lastPtr = NULL; |
| 1060 | for (i = 0; i < poolPtr->nhandles; ++i) { |
| 1061 | handlePtr = ns_malloc(sizeof(Handle)); |
| 1062 | <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringInit">Ns_DStringInit</a>(&handlePtr->dsExceptionMsg); |
| 1063 | handlePtr->poolPtr = poolPtr; |
| 1064 | handlePtr->connection = NULL; |
| 1065 | handlePtr->connected = NS_FALSE; |
| 1066 | handlePtr->fetchingRows = 0; |
| 1067 | handlePtr->row = <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetCreate">Ns_SetCreate</a>(NULL); |
| 1068 | handlePtr->cExceptionCode[0] = '\0'; |
| 1069 | handlePtr->otime = handlePtr->atime = 0; |
| 1070 | handlePtr->stale = NS_FALSE; |
| 1071 | handlePtr->stale_on_close = 0; |
| 1072 | |
| 1073 | /* |
| 1074 | * The following elements of the Handle structure could |
| 1075 | * be obtained by dereferencing the poolPtr. They're |
| 1076 | * only needed to maintain the original Ns_DbHandle |
| 1077 | * structure definition which was designed to allow |
| 1078 | * handles outside of pools, a feature no longer supported. |
| 1079 | */ |
| 1080 | |
| 1081 | handlePtr->driver = driver; |
| 1082 | handlePtr->datasource = poolPtr->source; |
| 1083 | handlePtr->user = poolPtr->user; |
| 1084 | handlePtr->password = poolPtr->pass; |
| 1085 | handlePtr->verbose = poolPtr->fVerbose; |
| 1086 | handlePtr->poolname = pool; |
| 1087 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_ReturnHandle">ReturnHandle</a>(handlePtr); |
| 1088 | } |
| 1089 | if (!<a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetInt">Ns_ConfigGetInt</a>(path, "checkinterval", &i) || i < 0) { |
| 1090 | i = 600; /* 10 minutes. */ |
| 1091 | } |
| 1092 | <a href="/cvs/aolserver/aolserver/nsd/sched.c#A_Ns_ScheduleProc">Ns_ScheduleProc</a>(<a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_CheckPool">CheckPool</a>, poolPtr, 0, i); |
| 1093 | return poolPtr; |
| 1094 | } |
| 1095 | |
| 1096 | |
| 1097 | /* |
| 1098 | *---------------------------------------------------------------------- |
| 1099 | * |
| 1100 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Connect">Connect</a> -- |
| 1101 | * |
| 1102 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Connect">Connect</a> a handle by opening the database. |
| 1103 | * |
| 1104 | * Results: |
| 1105 | * NS_OK if connect ok, NS_ERROR otherwise. |
| 1106 | * |
| 1107 | * Side effects: |
| 1108 | * None. |
| 1109 | * |
| 1110 | *---------------------------------------------------------------------- |
| 1111 | */ |
| 1112 | |
| 1113 | static int |
| 1114 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_Connect">Connect</a>(Handle *handlePtr) |
| 1115 | { |
| 1116 | int status; |
| 1117 | |
| 1118 | status = <a href="/cvs/aolserver/aolserver/nsdb/dbdrv.c#A_NsDbOpen">NsDbOpen</a>((Ns_DbHandle *) handlePtr); |
| 1119 | if (status != NS_OK) { |
| 1120 | handlePtr->connected = NS_FALSE; |
| 1121 | handlePtr->atime = handlePtr->otime = 0; |
| 1122 | handlePtr->stale = NS_FALSE; |
| 1123 | } else { |
| 1124 | handlePtr->connected = NS_TRUE; |
| 1125 | handlePtr->atime = handlePtr->otime = time(NULL); |
| 1126 | } |
| 1127 | |
| 1128 | return status; |
| 1129 | } |
| 1130 | |
| 1131 | |
| 1132 | /* |
| 1133 | *---------------------------------------------------------------------- |
| 1134 | * |
| 1135 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_IncrCount">IncrCount</a> -- |
| 1136 | * |
| 1137 | * Update per-thread count of allocated handles. |
| 1138 | * |
| 1139 | * Results: |
| 1140 | * Previous count of allocated handles. |
| 1141 | * |
| 1142 | * Side effects: |
| 1143 | * None. |
| 1144 | * |
| 1145 | *---------------------------------------------------------------------- |
| 1146 | */ |
| 1147 | |
| 1148 | static int |
| 1149 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_IncrCount">IncrCount</a>(Pool *poolPtr, int incr) |
| 1150 | { |
| 1151 | Tcl_HashTable *tablePtr; |
| 1152 | Tcl_HashEntry *hPtr; |
| 1153 | int prev, count, new; |
| 1154 | |
| 1155 | tablePtr = Ns_TlsGet(&tls); |
| 1156 | if (tablePtr == NULL) { |
| 1157 | tablePtr = ns_malloc(sizeof(Tcl_HashTable)); |
| 1158 | Tcl_InitHashTable(tablePtr, TCL_ONE_WORD_KEYS); |
| 1159 | Ns_TlsSet(&tls, tablePtr); |
| 1160 | } |
| 1161 | hPtr = Tcl_CreateHashEntry(tablePtr, (char *) poolPtr, &new); |
| 1162 | if (new) { |
| 1163 | prev = 0; |
| 1164 | } else { |
| 1165 | prev = (int) Tcl_GetHashValue(hPtr); |
| 1166 | } |
| 1167 | count = prev + incr; |
| 1168 | if (count == 0) { |
| 1169 | Tcl_DeleteHashEntry(hPtr); |
| 1170 | } else { |
| 1171 | Tcl_SetHashValue(hPtr, (ClientData) count); |
| 1172 | } |
| 1173 | return prev; |
| 1174 | } |
| 1175 | |
| 1176 | |
| 1177 | /* |
| 1178 | *---------------------------------------------------------------------- |
| 1179 | * |
| 1180 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_GetServer">GetServer</a> -- |
| 1181 | * |
| 1182 | * Get per-server data. |
| 1183 | * |
| 1184 | * Results: |
| 1185 | * Pointer to per-server data. |
| 1186 | * |
| 1187 | * Side effects: |
| 1188 | * None. |
| 1189 | * |
| 1190 | *---------------------------------------------------------------------- |
| 1191 | */ |
| 1192 | |
| 1193 | static ServData * |
| 1194 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_GetServer">GetServer</a>(char *server) |
| 1195 | { |
| 1196 | Tcl_HashEntry *hPtr; |
| 1197 | |
| 1198 | hPtr = Tcl_FindHashEntry(&serversTable, server); |
| 1199 | if (hPtr != NULL) { |
| 1200 | return Tcl_GetHashValue(hPtr); |
| 1201 | } |
| 1202 | return NULL; |
| 1203 | } |
| 1204 | |
| 1205 | |
| 1206 | /* |
| 1207 | *---------------------------------------------------------------------- |
| 1208 | * |
| 1209 | * <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_FreeTable">FreeTable</a> -- |
| 1210 | * |
| 1211 | * Free the per-thread count of allocated handles table. |
| 1212 | * |
| 1213 | * Results: |
| 1214 | * None. |
| 1215 | * |
| 1216 | * Side effects: |
| 1217 | * None. |
| 1218 | * |
| 1219 | *---------------------------------------------------------------------- |
| 1220 | */ |
| 1221 | |
| 1222 | static void |
| 1223 | <a href="/cvs/aolserver/aolserver/nsdb/dbinit.c#A_FreeTable">FreeTable</a>(void *arg) |
| 1224 | { |
| 1225 | Tcl_HashTable *tablePtr = arg; |
| 1226 | |
| 1227 | Tcl_DeleteHashTable(tablePtr); |
| 1228 | ns_free(tablePtr); |
| 1229 | } |
Copyright © 2010 Geeknet, Inc. All rights reserved. Terms of Use