There are no available options for this view.

Parent Directory Parent Directory | Revision <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> Revision <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a>

Revision 1.5 - (show annotations) (download) (as text)
Thu Feb 5 17:50:53 2004 UTC (8 years ago) by dossy
Branch: MAIN
CVS Tags: aolserver_v45_r0, HEAD
Branch point for: aolserver_v45_r1, aolserver_v45_r2, aolserver_v45_bp
Changes since 1.4: +2 -2 lines
File MIME type: text/x-chdr
* 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 }