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 May 8 02:37:23 2003 UTC (8 years, 9 months ago) by seryakov
Branch: MAIN
CVS Tags: HEAD
Changes since 1.4: +12 -6 lines
File MIME type: text/x-chdr
added pattern to names command
1
2 /*
3 * The contents of this file are subject to the AOLserver Public License
4 * Version 1.1 (the "License"); you may not use this file except in
5 * compliance with the License. You may obtain a copy of the License at
6 * http://aolserver.lcs.mit.edu/.
7 *
8 * Software distributed under the License is distributed on an "AS IS"
9 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
10 * the License for the specific language governing rights and limitations
11 * under the License.
12 *
13 * The Original Code is ArsDigita code and related documentation
14 * distributed by ArsDigita.
15 *
16 * The Initial Developer of the Original Code is ArsDigita.,
17 * Portions created by ArsDigita are Copyright (C) 1999 ArsDigita.
18 * All Rights Reserved.
19 *
20 * Alternatively, the contents of this file may be used under the terms
21 * of the GNU General Public License (the "GPL"), in which case the
22 * provisions of GPL are applicable instead of those above. If you wish
23 * to allow use of your version of this file only under the terms of the
24 * GPL and not to allow others to use your version of this file under the
25 * License, indicate your decision by deleting the provisions above and
26 * replace them with the notice and other provisions required by the GPL.
27 * If you do not delete the provisions above, a recipient may use your
28 * version of this file under either the License or the GPL.
29 */
30
31 /*
32 * Added ns_cache incr command, Vlad Seryakov vlad@crystalballinc.com
33 *
34 * 2003-03-13: Don Baccus dhogaza@pacifier.com
35 * Added virtual server support and cleaned up warnings
36 *
37 * 2003-03-16: Zoran Vasiljevic zoran@archiware.com
38 * Added support for process-wide caches
39 */
40
41 /*
42 * tclcache.c --
43 *
44 * Tcl API for cache.c. Only works in nsd8x and AOLserver 4x and better.
45 */
46
47 static const char *RCSID = "@(#) $Header: /cvsroot-fuse/aolserver/nscache/tclcache.c,v 1.5 2003/05/08 02:37:23 seryakov Exp $, compiled: " __DATE__ " " __TIME__;
48
49 #ifndef USE_TCL8X
50 #define USE_TCL8X
51 #endif
52
53 #include "ns.h"
54
55 typedef int TclCacheCmdProc(Ns_Cache *cache, int needsLocking,
56 Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]);
57
58 typedef struct {
59 Ns_Cache *nscache;
60
61 TclCacheCmdProc *evalPtr;
62 TclCacheCmdProc *flushPtr;
63 TclCacheCmdProc *getPtr;
64 TclCacheCmdProc *namesPtr;
65 TclCacheCmdProc *setPtr;
66 TclCacheCmdProc *incrPtr;
67 } TclCache;
68
69 typedef struct {
70
71 /* If it's a global cache... */
72 TclCache *globalCache;
73
74 /* If globalCache == NULL */
75 Ns_Tls tls; /* the tls value is a TclCache */
76 int maxSize; /* use when creating a new thread-private cache */
77
78 } TclCacheInfo;
79
80 typedef struct {
81
82 int length;
83 char *value;
84
85 /*
86 * If value == NULL, then some thread is computing the value.
87 * This flag tells that thread that the entry has been flushed,
88 * so it should not store the value in the cache.
89 */
90 int flushed;
91
92 } GlobalValue;
93
94 /* Each virtual server gets its own cache and lock */
95
96 typedef struct {
97 Tcl_HashTable tclCaches;
98 Ns_Mutex lock;
99 } Server;
100
101 /* Global symbols */
102
103 int Ns_ModuleVersion = 1;
104
105 /* Common cache, used for all virtual servers */
106 static Server *commonCache;
107
108 int Ns_ModuleInit(char *server, char *module);
109
110 /* Private symbols */
111
112 static int <a href="/cvs/aolserver/nscache/tclcache.c#A_CacheInterpInit">CacheInterpInit</a>(Tcl_Interp *interp, void *context);
113 static Tcl_ObjCmdProc <a href="/cvs/aolserver/nscache/tclcache.c#A_NsTclCacheCmd">NsTclCacheCmd</a>;
114
115 static TclCache *<a href="/cvs/aolserver/nscache/tclcache.c#A_TclCacheFind">TclCacheFind</a>(Server *servPtr, char *name, int *needsLockingPtr);
116 static TclCache *<a href="/cvs/aolserver/nscache/tclcache.c#A_CacheFind">CacheFind</a>(Server *servPtr, char *name, int *needsLockingPtr);
117 static TclCache *<a href="/cvs/aolserver/nscache/tclcache.c#A_GetThreadCache">GetThreadCache</a>(char *name, TclCacheInfo *info);
118
119 static int <a href="/cvs/aolserver/nscache/tclcache.c#A_CreateCmd">CreateCmd</a>(Tcl_Interp *interp, Server *servPtr, int objc, Tcl_Obj * CONST objv[]);
120 static int <a href="/cvs/aolserver/nscache/tclcache.c#A_CreateThreadCache">CreateThreadCache</a>(Tcl_Interp *interp, Server *servPtr, char *name, int maxSize);
121 static int <a href="/cvs/aolserver/nscache/tclcache.c#A_CreateGlobalCache">CreateGlobalCache</a>(Tcl_Interp *interp, Server *servPtr, char *name,
122 int maxSize, int timeout);
123
124 static TclCacheCmdProc <a href="/cvs/aolserver/nscache/tclcache.c#A_ThreadCacheEvalCmd">ThreadCacheEvalCmd</a>;
125 static TclCacheCmdProc <a href="/cvs/aolserver/nscache/tclcache.c#A_ThreadCacheGetCmd">ThreadCacheGetCmd</a>;
126 static TclCacheCmdProc <a href="/cvs/aolserver/nscache/tclcache.c#A_ThreadCacheSetCmd">ThreadCacheSetCmd</a>;
127 static TclCacheCmdProc <a href="/cvs/aolserver/nscache/tclcache.c#A_ThreadCacheIncrCmd">ThreadCacheIncrCmd</a>;
128
129 static TclCacheCmdProc <a href="/cvs/aolserver/nscache/tclcache.c#A_GlobalCacheEvalCmd">GlobalCacheEvalCmd</a>;
130 static TclCacheCmdProc <a href="/cvs/aolserver/nscache/tclcache.c#A_GlobalCacheGetCmd">GlobalCacheGetCmd</a>;
131 static TclCacheCmdProc <a href="/cvs/aolserver/nscache/tclcache.c#A_GlobalCacheSetCmd">GlobalCacheSetCmd</a>;
132 static TclCacheCmdProc <a href="/cvs/aolserver/nscache/tclcache.c#A_GlobalCacheIncrCmd">GlobalCacheIncrCmd</a>;
133
134 static TclCacheCmdProc <a href="/cvs/aolserver/nscache/tclcache.c#A_FlushCmd">FlushCmd</a>;
135 static TclCacheCmdProc <a href="/cvs/aolserver/nscache/tclcache.c#A_NamesCmd">NamesCmd</a>;
136
137 static Ns_Callback <a href="/cvs/aolserver/nscache/tclcache.c#A_ThreadValueFree">ThreadValueFree</a>;
138 static Ns_Callback <a href="/cvs/aolserver/nscache/tclcache.c#A_GlobalValueFree">GlobalValueFree</a>;
139
140 static Ns_TlsCleanup <a href="/cvs/aolserver/nscache/tclcache.c#A_CleanupThreadCache">CleanupThreadCache</a>;
141
142 static Ns_Entry *<a href="/cvs/aolserver/nscache/tclcache.c#A_GetGlobalEntry">GetGlobalEntry</a>(Ns_Cache *cache, char *key, int create);
143 static int <a href="/cvs/aolserver/nscache/tclcache.c#A_CompleteEntryP">CompleteEntryP</a>(Ns_Entry *entry);
144
145
146 /*
147 *----------------------------------------------------------------------
148 *
149 * Ns_ModuleInit --
150 *
151 * Initialize this module.
152 *
153 * Results:
154 * Standard AOLserver return code..
155 *
156 * Side effects:
157 * On very first invocation, create and initialize process-wide
158 * descriptor handling common caches.
159 *
160 *----------------------------------------------------------------------
161 */
162 int
163 Ns_ModuleInit(char *server, char *module)
164 {
165 static int initCommon = 0;
166 Server *servPtr;
167
168 <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Notice, "nscache module version @VER@ server: %s", server);
169
170 /*
171 * Initialize cache descriptor for process-wide caches
172 */
173
174 if (initCommon == 0) {
175 Ns_MasterLock();
176 if (initCommon == 0) {
177 commonCache = ns_malloc(sizeof(Server));
178 Tcl_InitHashTable(&commonCache->tclCaches, TCL_STRING_KEYS);
179 Ns_MutexInit(&commonCache->lock);
180 Ns_MutexSetName(&commonCache->lock, "nscache:commonTclCaches");
181 initCommon = 1;
182 }
183 Ns_MasterUnlock();
184 }
185
186 /*
187 * Initialize per-virtual-server cache descriptor
188 */
189
190 servPtr = ns_malloc(sizeof(Server));
191 Tcl_InitHashTable(&servPtr->tclCaches, TCL_STRING_KEYS);
192 Ns_MutexInit(&servPtr->lock);
193 Ns_MutexSetName2(&servPtr->lock, "nscache:tclCaches", server);
194 <a href="/cvs/aolserver/aolserver/nsd/tclinit.c#A_Ns_TclInitInterps">Ns_TclInitInterps</a>(server, (Ns_TclInterpInitProc *) <a href="/cvs/aolserver/nscache/tclcache.c#A_CacheInterpInit">CacheInterpInit</a>,
195 (void *) servPtr);
196
197 return NS_OK;
198 }
199
200 /*
201 *----------------------------------------------------------------------
202 *
203 * <a href="/cvs/aolserver/nscache/tclcache.c#A_CacheInterpInit">CacheInterpInit</a> --
204 *
205 * Add ns_cache commands to the given interp.
206 *
207 * Results:
208 * Standard AOLserver return code.
209 *
210 * Side effects:
211 * None.
212 *
213 *----------------------------------------------------------------------
214 */
215 static int
216 <a href="/cvs/aolserver/nscache/tclcache.c#A_CacheInterpInit">CacheInterpInit</a>(Tcl_Interp *interp, void *context)
217 {
218 Tcl_Command cacheCmd;
219
220 cacheCmd = Tcl_CreateObjCommand(interp, "ns_cache", <a href="/cvs/aolserver/nscache/tclcache.c#A_NsTclCacheCmd">NsTclCacheCmd</a>,
221 (ClientData) context, NULL);
222
223 return (cacheCmd != NULL) ? NS_OK : NS_ERROR;
224 }
225
226 /*
227 *----------------------------------------------------------------------
228 *
229 * <a href="/cvs/aolserver/nscache/tclcache.c#A_GetThreadCache">GetThreadCache</a> --
230 *
231 * Locate the per-thread cache.
232 *
233 * Results:
234 * A cache private to the current thread and virtual server.
235 *
236 * Side effects:
237 * A new cache may be allocated.
238 *
239 *----------------------------------------------------------------------
240 */
241
242 static TclCache *
243 <a href="/cvs/aolserver/nscache/tclcache.c#A_GetThreadCache">GetThreadCache</a>(char *name, TclCacheInfo *info)
244 {
245 TclCache *cache;
246 Ns_DString ds;
247 char tid[20];
248
249 cache = (TclCache *) Ns_TlsGet(&info->tls);
250
251 if (cache == NULL) {
252 cache = ns_calloc(1, sizeof *cache);
253
254 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringInit">Ns_DStringInit</a>(&ds);
255 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppend">Ns_DStringAppend</a>(&ds, name);
256 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppend">Ns_DStringAppend</a>(&ds, ".");
257 sprintf(tid, "%d", Ns_ThreadId());
258 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppend">Ns_DStringAppend</a>(&ds, tid);
259
260 cache->nscache = <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheCreateSz">Ns_CacheCreateSz</a>(<a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringValue">Ns_DStringValue</a>(&ds),
261 TCL_STRING_KEYS, (size_t) info->maxSize, <a href="/cvs/aolserver/nscache/tclcache.c#A_ThreadValueFree">ThreadValueFree</a>);
262
263 cache->evalPtr = <a href="/cvs/aolserver/nscache/tclcache.c#A_ThreadCacheEvalCmd">ThreadCacheEvalCmd</a>;
264 cache->flushPtr = <a href="/cvs/aolserver/nscache/tclcache.c#A_FlushCmd">FlushCmd</a>;
265 cache->getPtr = <a href="/cvs/aolserver/nscache/tclcache.c#A_ThreadCacheGetCmd">ThreadCacheGetCmd</a>;
266 cache->namesPtr = <a href="/cvs/aolserver/nscache/tclcache.c#A_NamesCmd">NamesCmd</a>;
267 cache->setPtr = <a href="/cvs/aolserver/nscache/tclcache.c#A_ThreadCacheSetCmd">ThreadCacheSetCmd</a>;
268 cache->incrPtr = <a href="/cvs/aolserver/nscache/tclcache.c#A_ThreadCacheIncrCmd">ThreadCacheIncrCmd</a>;
269
270 Ns_TlsSet(&info->tls, cache);
271 }
272
273 return cache;
274 }
275
276 /*
277 *----------------------------------------------------------------------
278 *
279 * <a href="/cvs/aolserver/nscache/tclcache.c#A_TclCacheFind">TclCacheFind</a> --
280 *
281 * Locates the named cache for the given virtual server.
282 *
283 * Results:
284 * The appropriate cache (global or thread-private) for the
285 * specified name. If the cache is global, sets *globalPtr to
286 * NS_TRUE, else sets it to NS_FALSE.
287 *
288 * Side effects:
289 * A new thread-private cache may be created.
290 *
291 *----------------------------------------------------------------------
292 */
293
294 static TclCache *
295 <a href="/cvs/aolserver/nscache/tclcache.c#A_TclCacheFind">TclCacheFind</a>(Server *servPtr, char *name, int *needsLockingPtr)
296 {
297 TclCache *cache = NULL;
298
299 cache = <a href="/cvs/aolserver/nscache/tclcache.c#A_CacheFind">CacheFind</a>(servPtr, name, needsLockingPtr);
300 if (cache == NULL) {
301 cache = <a href="/cvs/aolserver/nscache/tclcache.c#A_CacheFind">CacheFind</a>(commonCache, name, needsLockingPtr);
302 }
303
304 return cache;
305 }
306
307 /*
308 *----------------------------------------------------------------------
309 *
310 * <a href="/cvs/aolserver/nscache/tclcache.c#A_CreateThreadCache">CreateThreadCache</a> --
311 *
312 * Create a thread cache. Actually, just create the TclCacheInfo
313 * for it.
314 *
315 * Results:
316 * TCL result.
317 *
318 * Side effects:
319 * Adds a TclCacheInfo to tclCaches.
320 *
321 *----------------------------------------------------------------------
322 */
323
324 static int
325 <a href="/cvs/aolserver/nscache/tclcache.c#A_CreateThreadCache">CreateThreadCache</a>(Tcl_Interp *interp, Server *servPtr, char *name, int maxSize)
326 {
327 TclCacheInfo *iPtr;
328 Tcl_HashEntry *hPtr;
329 int new;
330
331 Ns_MutexLock(&servPtr->lock);
332
333 hPtr = Tcl_CreateHashEntry(&servPtr->tclCaches, name, &new);
334 if (!new) {
335 Tcl_AppendResult(interp, "a cache named ", name,
336 " already exists", NULL);
337
338 Ns_MutexUnlock(&servPtr->lock);
339 return TCL_ERROR;
340 }
341
342 iPtr = ns_malloc(sizeof *iPtr);
343 iPtr->globalCache = NULL;
344 Ns_TlsAlloc(&iPtr->tls, <a href="/cvs/aolserver/nscache/tclcache.c#A_CleanupThreadCache">CleanupThreadCache</a>);
345 iPtr->maxSize = maxSize;
346
347 Tcl_SetHashValue(hPtr, iPtr);
348
349 Ns_MutexUnlock(&servPtr->lock);
350 return TCL_OK;
351 }
352
353 /*
354 *----------------------------------------------------------------------
355 *
356 * <a href="/cvs/aolserver/nscache/tclcache.c#A_CreateGlobalCache">CreateGlobalCache</a> --
357 *
358 * Create a global cache.
359 *
360 * Results:
361 * TCL result.
362 *
363 * Side effects:
364 * Adds a TclCacheInfo to tclCaches.
365 *
366 *----------------------------------------------------------------------
367 */
368
369 static int
370 <a href="/cvs/aolserver/nscache/tclcache.c#A_CreateGlobalCache">CreateGlobalCache</a>(Tcl_Interp *interp, Server *servPtr, char *name, int maxSize,
371 int timeout)
372 {
373 TclCacheInfo *iPtr;
374 Tcl_HashEntry *hPtr;
375 int new;
376
377 Ns_MutexLock(&servPtr->lock);
378
379 hPtr = Tcl_CreateHashEntry(&servPtr->tclCaches, name, &new);
380 if (!new) {
381 Tcl_AppendResult(interp, "a cache named ", name,
382 " already exists", NULL);
383
384 Ns_MutexUnlock(&servPtr->lock);
385 return TCL_ERROR;
386 }
387
388 iPtr = ns_malloc(sizeof *iPtr);
389 iPtr->globalCache = ns_malloc(sizeof *iPtr->globalCache);
390 if (maxSize > 0) {
391 iPtr->globalCache->nscache = <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheCreateSz">Ns_CacheCreateSz</a>(name,
392 TCL_STRING_KEYS, (size_t) maxSize, <a href="/cvs/aolserver/nscache/tclcache.c#A_GlobalValueFree">GlobalValueFree</a>);
393 } else {
394 iPtr->globalCache->nscache = <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheCreate">Ns_CacheCreate</a>(name,
395 TCL_STRING_KEYS, timeout, <a href="/cvs/aolserver/nscache/tclcache.c#A_GlobalValueFree">GlobalValueFree</a>);
396 }
397 iPtr->globalCache->evalPtr = <a href="/cvs/aolserver/nscache/tclcache.c#A_GlobalCacheEvalCmd">GlobalCacheEvalCmd</a>;
398 iPtr->globalCache->flushPtr = <a href="/cvs/aolserver/nscache/tclcache.c#A_FlushCmd">FlushCmd</a>;
399 iPtr->globalCache->getPtr = <a href="/cvs/aolserver/nscache/tclcache.c#A_GlobalCacheGetCmd">GlobalCacheGetCmd</a>;
400 iPtr->globalCache->namesPtr = <a href="/cvs/aolserver/nscache/tclcache.c#A_NamesCmd">NamesCmd</a>;
401 iPtr->globalCache->setPtr = <a href="/cvs/aolserver/nscache/tclcache.c#A_GlobalCacheSetCmd">GlobalCacheSetCmd</a>;
402 iPtr->globalCache->incrPtr = <a href="/cvs/aolserver/nscache/tclcache.c#A_GlobalCacheIncrCmd">GlobalCacheIncrCmd</a>;
403
404 Tcl_SetHashValue(hPtr, iPtr);
405
406 Ns_MutexUnlock(&servPtr->lock);
407 return TCL_OK;
408 }
409
410
411 /*
412 *----------------------------------------------------------------------
413 *
414 * <a href="/cvs/aolserver/nscache/tclcache.c#A_CreateCmd">CreateCmd</a> --
415 *
416 * Create a cache.
417 *
418 * Results:
419 * TCL result.
420 *
421 * Side effects:
422 * Creates a new cache.
423 *
424 *----------------------------------------------------------------------
425 */
426
427 static int
428 <a href="/cvs/aolserver/nscache/tclcache.c#A_CreateCmd">CreateCmd</a>(Tcl_Interp *interp, Server *servPtr, int objc, Tcl_Obj * CONST objv[])
429 {
430 int obji, n;
431 char *arg;
432 int maxSize = -1;
433 int timeout = -1;
434 int thread = -1;
435 int common = -1;
436 char *name;
437
438 if (objc < 3) {
439 Tcl_AppendResult(interp, "missing cache-name argument", NULL);
440 return TCL_ERROR;
441 }
442
443 for (obji = 3; obji < objc; obji++) {
444 arg = Tcl_GetString(objv[obji]);
445
446 if (STREQ(arg, "-size") || STREQ(arg, "-timeout")) {
447
448 if (obji + 1 >= objc) {
449 Tcl_AppendResult(interp, arg,
450 " requires an argument", NULL);
451 return TCL_ERROR;
452 }
453
454 if (timeout != -1 || maxSize != -1) {
455 Tcl_AppendResult(interp,
456 "only one of -size and -timeout is allowed", NULL);
457 return TCL_ERROR;
458 }
459
460 if (Tcl_GetIntFromObj(interp, objv[obji+1], &n) != TCL_OK) {
461 return TCL_ERROR;
462 }
463
464 if (n < 0) {
465 Tcl_AppendResult(interp, arg + 1,
466 " must be at least 0", NULL);
467 return TCL_ERROR;
468 }
469
470 if (arg[1] == 's') {
471 maxSize = n;
472 } else {
473 timeout = n;
474 }
475
476 obji++;
477 }
478
479 else if (STREQ(arg, "-thread")) {
480 if (obji + 1 >= objc) {
481 Tcl_AppendResult(interp, arg,
482 " requires an argument", NULL);
483 return TCL_ERROR;
484 }
485
486 if (thread != -1) {
487 Tcl_AppendResult(interp, arg,
488 " may only be given once", NULL);
489 return TCL_ERROR;
490 }
491
492 if (common != -1) {
493 Tcl_AppendResult(interp, arg,
494 " may not be used together with -serverwide option", NULL);
495 return TCL_ERROR;
496 }
497
498 if (Tcl_GetBooleanFromObj(interp, objv[obji+1], &thread)
499 != TCL_OK)
500 {
501 return TCL_ERROR;
502 }
503
504 obji++;
505 }
506
507 else if (STREQ(arg, "-serverwide")) {
508 if (obji + 1 >= objc) {
509 Tcl_AppendResult(interp, arg,
510 " requires an argument", NULL);
511 return TCL_ERROR;
512 }
513
514 if (common != -1) {
515 Tcl_AppendResult(interp, arg,
516 " may only be given once", NULL);
517 return TCL_ERROR;
518 }
519
520 if (thread != -1) {
521 Tcl_AppendResult(interp, arg,
522 " may not be used together with -thread option", NULL);
523 return TCL_ERROR;
524 }
525
526 if (Tcl_GetBooleanFromObj(interp, objv[obji+1], &common)
527 != TCL_OK)
528 {
529 return TCL_ERROR;
530 }
531
532 obji++;
533 }
534
535 else {
536 Tcl_AppendResult(interp, "unknown flag ", arg, "; should be \"",
537 Tcl_GetString(objv[0]), " ", Tcl_GetString(objv[1]),
538 " cache-name ?-size size? ?-timeout timeout?"
539 " ?-thread boolean | -serverwide boolean?", NULL);
540 return TCL_ERROR;
541 }
542 }
543
544 name = Tcl_GetString(objv[2]);
545
546 if (timeout < 0 && maxSize < 0) {
547 timeout = 0;
548 maxSize = 0;
549 }
550
551 if (thread < 0) {
552 thread = 0;
553 }
554
555 if (common < 0) {
556 common = 0;
557 }
558
559 if (thread && timeout > 0) {
560 Tcl_AppendResult(interp,
561 "thread-private cache cannot have a timeout", NULL);
562 return TCL_ERROR;
563 }
564
565 if (common) {
566 return <a href="/cvs/aolserver/nscache/tclcache.c#A_CreateGlobalCache">CreateGlobalCache</a>(interp, commonCache, name, maxSize, timeout);
567 }
568
569 else if (thread) {
570 return <a href="/cvs/aolserver/nscache/tclcache.c#A_CreateThreadCache">CreateThreadCache</a>(interp, servPtr, name, maxSize);
571 }
572
573 else {
574 return <a href="/cvs/aolserver/nscache/tclcache.c#A_CreateGlobalCache">CreateGlobalCache</a>(interp, servPtr, name, maxSize, timeout);
575 }
576 }
577
578 /*
579 *----------------------------------------------------------------------
580 *
581 * <a href="/cvs/aolserver/nscache/tclcache.c#A_NamesCmd">NamesCmd</a> --
582 *
583 * Get a list of all the entry names in a cache.
584 *
585 * Results:
586 * Tcl result.
587 *
588 * Side effects:
589 * None.
590 *
591 *----------------------------------------------------------------------
592 */
593
594 static int
595 <a href="/cvs/aolserver/nscache/tclcache.c#A_NamesCmd">NamesCmd</a>(Ns_Cache *cache, int needsLocking, Tcl_Interp *interp, int objc,
596 Tcl_Obj * CONST objv[])
597 {
598 Ns_CacheSearch search;
599 Ns_Entry *ePtr;
600 Tcl_Obj *namePtr;
601 Tcl_Obj *resultPtr;
602 char *pattern = 0;
603 char *key;
604 int status;
605
606 if (objc < 3) {
607 Tcl_AppendResult(interp, "wrong # args: should be \"",
608 Tcl_GetString(objv[0]), " ",
609 Tcl_GetString(objv[1]), " cache ?pattern?\"", NULL);
610 return TCL_ERROR;
611 }
612
613 if (needsLocking)
614 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheLock">Ns_CacheLock</a>(cache);
615
616 status = TCL_OK;
617 if(objc > 3) pattern = Tcl_GetString(objv[3]);
618 resultPtr = Tcl_GetObjResult(interp);
619 ePtr = <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheFirstEntry">Ns_CacheFirstEntry</a>(cache, &search);
620
621 while (ePtr != NULL) {
622 key = <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheKey">Ns_CacheKey</a>(ePtr);
623 if(!pattern || Tcl_StringMatch(key,pattern)) {
624 namePtr = Tcl_NewStringObj(key, -1);
625 if (Tcl_ListObjAppendElement(interp, resultPtr, namePtr) != TCL_OK) {
626 Tcl_DecrRefCount(namePtr);
627 status = TCL_ERROR;
628 break;
629 }
630 }
631 ePtr = <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheNextEntry">Ns_CacheNextEntry</a>(&search);
632 }
633
634 if (needsLocking)
635 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheUnlock">Ns_CacheUnlock</a>(cache);
636
637 return status;
638 }
639
640 /*
641 *----------------------------------------------------------------------
642 *
643 * <a href="/cvs/aolserver/nscache/tclcache.c#A_FlushCmd">FlushCmd</a> --
644 *
645 * Remove an entry from the cache by key.
646 *
647 * Results:
648 * TCL result.
649 *
650 * Side effects:
651 * None.
652 *
653 *----------------------------------------------------------------------
654 */
655
656 static int
657 <a href="/cvs/aolserver/nscache/tclcache.c#A_FlushCmd">FlushCmd</a>(Ns_Cache *cache, int needsLocking, Tcl_Interp *interp, int objc,
658 Tcl_Obj * CONST objv[])
659 {
660 Ns_Entry *ePtr;
661
662 if (objc != 4) {
663 Tcl_AppendResult(interp,"wrong # args: should be \"",
664 Tcl_GetString(objv[0]), " ", Tcl_GetString(objv[1]),
665 " cache key\"", NULL);
666 return TCL_ERROR;
667 }
668
669 if (needsLocking)
670 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheLock">Ns_CacheLock</a>(cache);
671
672 ePtr = <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheFindEntry">Ns_CacheFindEntry</a>(cache, Tcl_GetString(objv[3]));
673
674 if (ePtr != NULL) {
675 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheFlushEntry">Ns_CacheFlushEntry</a>(ePtr);
676 if (needsLocking)
677 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheBroadcast">Ns_CacheBroadcast</a>(cache);
678 }
679
680 if (needsLocking)
681 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheUnlock">Ns_CacheUnlock</a>(cache);
682
683 return TCL_OK;
684 }
685
686 /*
687 *----------------------------------------------------------------------
688 *
689 * IncompleteEntryP --
690 *
691 * Results:
692 * NS_TRUE if the cache value is complete, else NS_FALSE.
693 *
694 * Side effects:
695 * None.
696 *
697 *----------------------------------------------------------------------
698 */
699
700 static int
701 <a href="/cvs/aolserver/nscache/tclcache.c#A_CompleteEntryP">CompleteEntryP</a>(Ns_Entry *ePtr)
702 {
703 return ((GlobalValue *)<a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheGetValue">Ns_CacheGetValue</a>(ePtr))->value != NULL;
704 }
705
706 /*
707 *----------------------------------------------------------------------
708 *
709 * <a href="/cvs/aolserver/nscache/tclcache.c#A_GetGlobalEntry">GetGlobalEntry</a> --
710 *
711 * Given a locked global cache and a key, get the cache entry.
712 * If the key is not found and create is set, then create a new,
713 * incomplete entry and return it. If the key is not found and
714 * create is not set, then return NULL. If the key is found but
715 * the entry is incomplete, wait until the entry is complete or
716 * deleted.
717 * If the key is found and the entry is complete, return it.
718 *
719 * Results:
720 * If create is set, a new or complete cache entry.
721 * If create is not set, NULL or a complete cache entry.
722 *
723 * Side effects:
724 * None.
725 *
726 *----------------------------------------------------------------------
727 */
728
729 static Ns_Entry *
730 <a href="/cvs/aolserver/nscache/tclcache.c#A_GetGlobalEntry">GetGlobalEntry</a>(Ns_Cache *cache, char *key, int create)
731 {
732 Ns_Entry *ePtr;
733 GlobalValue *vPtr;
734 int new = 0;
735
736 while (1) {
737 if (create) {
738 ePtr = <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheCreateEntry">Ns_CacheCreateEntry</a>(cache, key, &new);
739
740 if (new) {
741 vPtr = ns_malloc(sizeof *vPtr);
742 vPtr->value = NULL;
743 vPtr->length = 0;
744 vPtr->flushed = NS_FALSE;
745 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheSetValueSz">Ns_CacheSetValueSz</a>(ePtr, vPtr, 0);
746
747 break;
748 }
749 }
750
751 else {
752 ePtr = <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheFindEntry">Ns_CacheFindEntry</a>(cache, key);
753
754 if (ePtr == NULL) {
755 break;
756 }
757 }
758
759 if (<a href="/cvs/aolserver/nscache/tclcache.c#A_CompleteEntryP">CompleteEntryP</a>(ePtr)) {
760 break;
761 }
762
763 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheWait">Ns_CacheWait</a>(cache);
764 }
765
766 return ePtr;
767 }
768
769 /*
770 *----------------------------------------------------------------------
771 *
772 * <a href="/cvs/aolserver/nscache/tclcache.c#A_GlobalCacheGetCmd">GlobalCacheGetCmd</a> --
773 *
774 * Get a value from the cache given a key. If some other thread is
775 * currently in an eval for the same cache and key, block until
776 * that thread finishes, then use the value it computed.
777 *
778 * Results:
779 * TCL result.
780 *
781 * Side effects:
782 * None.
783 *
784 *----------------------------------------------------------------------
785 */
786
787 static int
788 <a href="/cvs/aolserver/nscache/tclcache.c#A_GlobalCacheGetCmd">GlobalCacheGetCmd</a>(Ns_Cache *cache, int needsLocking, Tcl_Interp *interp,
789 int objc, Tcl_Obj * CONST objv[])
790 {
791 char *key;
792 char *varname;
793 Tcl_Obj *resultPtr;
794 Tcl_Obj *newValuePtr;
795 Ns_Entry *ePtr;
796 GlobalValue *vPtr;
797 int status = TCL_OK;
798
799 if (objc == 4) {
800 varname = NULL;
801 }
802
803 else if (objc == 5) {
804 varname = Tcl_GetString(objv[4]);
805 }
806
807 else {
808 Tcl_AppendResult(interp, "wrong # args: should be \"",
809 Tcl_GetString(objv[0]), " ",
810 Tcl_GetString(objv[1]), " cache key ?varname?\"", NULL);
811 return TCL_ERROR;
812 }
813
814 resultPtr = Tcl_GetObjResult(interp);
815 key = Tcl_GetString(objv[3]);
816
817 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheLock">Ns_CacheLock</a>(cache);
818
819 ePtr = <a href="/cvs/aolserver/nscache/tclcache.c#A_GetGlobalEntry">GetGlobalEntry</a>(cache, key, 0);
820
821 if (ePtr == NULL) {
822
823 if (varname == NULL) {
824 Tcl_AppendStringsToObj(resultPtr, "no such key: ", key, NULL);
825 status = TCL_ERROR;
826 } else {
827 Tcl_SetBooleanObj(resultPtr, 0);
828 }
829
830 } else {
831
832 vPtr = (GlobalValue *) <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheGetValue">Ns_CacheGetValue</a>(ePtr);
833 if (varname == NULL) {
834 Tcl_SetStringObj(resultPtr, vPtr->value, vPtr->length);
835 } else {
836 Tcl_SetBooleanObj(resultPtr, 1);
837
838 newValuePtr = Tcl_NewStringObj(vPtr->value, vPtr->length);
839 if (Tcl_SetVar2Ex(interp, varname, NULL, newValuePtr,
840 TCL_LEAVE_ERR_MSG) == NULL)
841 {
842 status = TCL_ERROR;
843 Tcl_DecrRefCount(newValuePtr);
844 }
845 }
846
847 }
848
849 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheUnlock">Ns_CacheUnlock</a>(cache);
850
851 return status;
852 }
853
854 /*
855 *----------------------------------------------------------------------
856 *
857 * <a href="/cvs/aolserver/nscache/tclcache.c#A_GlobalCacheEvalCmd">GlobalCacheEvalCmd</a> --
858 *
859 * Get a value from the cache given a key. If the key is not in
860 * the cache, evaluate the code block and store its result as the
861 * value for the key. If some other thread is currently in an
862 * eval for the same cache and key, block until that thread
863 * finishes, then use the value it computed.
864 *
865 * Results:
866 * TCL result.
867 *
868 * Side effects:
869 * None.
870 *
871 *----------------------------------------------------------------------
872 */
873
874 static int
875 <a href="/cvs/aolserver/nscache/tclcache.c#A_GlobalCacheEvalCmd">GlobalCacheEvalCmd</a>(Ns_Cache *cache, int needsLocking, Tcl_Interp *interp,
876 int objc, Tcl_Obj * CONST objv[])
877 {
878 Ns_Entry *ePtr;
879 GlobalValue *vPtr;
880 int status;
881 char *string;
882 int length;
883
884 if (objc != 5) {
885 Tcl_AppendResult(interp, "wrong # args: should be \"",
886 Tcl_GetString(objv[0]), " ",
887 Tcl_GetString(objv[1]), " cache key code\"", NULL);
888 return TCL_ERROR;
889 }
890
891 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheLock">Ns_CacheLock</a>(cache);
892
893 ePtr = <a href="/cvs/aolserver/nscache/tclcache.c#A_GetGlobalEntry">GetGlobalEntry</a>(cache, Tcl_GetString(objv[3]), 1);
894 vPtr = (GlobalValue *)<a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheGetValue">Ns_CacheGetValue</a>(ePtr);
895
896 if (vPtr->value != NULL) {
897 Tcl_SetStringObj(Tcl_GetObjResult(interp),
898 vPtr->value, vPtr->length);
899 status = TCL_OK;
900 }
901
902 else {
903 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheUnlock">Ns_CacheUnlock</a>(cache);
904 status = Tcl_EvalObjEx(interp, objv[4], 0);
905 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheLock">Ns_CacheLock</a>(cache);
906
907 if (status == TCL_OK || status == TCL_RETURN) {
908 if (vPtr->flushed) {
909 /* Cache entry was flushed while we were in Tcl_Eval. */
910 ns_free(vPtr);
911 } else {
912 string = Tcl_GetStringFromObj(Tcl_GetObjResult(interp),
913 &length);
914 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheSetValueSz">Ns_CacheSetValueSz</a>(ePtr, vPtr, (size_t) length);
915 vPtr->value = ns_malloc((size_t) length);
916 memcpy(vPtr->value, string, (size_t) length);
917 vPtr->length = length;
918 vPtr->flushed = 0;
919 }
920 status = TCL_OK;
921 }
922
923 else {
924 if (!vPtr->flushed) {
925 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheDeleteEntry">Ns_CacheDeleteEntry</a>(ePtr);
926 }
927 ns_free(vPtr);
928 }
929
930 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheBroadcast">Ns_CacheBroadcast</a>(cache);
931 }
932
933 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheUnlock">Ns_CacheUnlock</a>(cache);
934
935 return status;
936 }
937
938 /*
939 *----------------------------------------------------------------------
940 *
941 * <a href="/cvs/aolserver/nscache/tclcache.c#A_GlobalCacheSetCmd">GlobalCacheSetCmd</a> --
942 *
943 * Store the key/value pair in the cache, flushing any previous
944 * value for the key.
945 *
946 * Results:
947 * TCL_OK
948 *
949 * Side effects:
950 * None.
951 *
952 *----------------------------------------------------------------------
953 */
954
955 static int
956 <a href="/cvs/aolserver/nscache/tclcache.c#A_GlobalCacheSetCmd">GlobalCacheSetCmd</a>(Ns_Cache *cache, int needsLocking, Tcl_Interp *interp,
957 int objc, Tcl_Obj * CONST objv[])
958 {
959 char *key;
960 char *value;
961 Ns_Entry *ePtr;
962 GlobalValue *vPtr;
963 int new;
964
965 if (objc != 5) {
966 Tcl_AppendResult(interp, "wrong # args: should be \"",
967 Tcl_GetString(objv[0]), " ",
968 Tcl_GetString(objv[1]), " cache key value\"", NULL);
969 return TCL_ERROR;
970 }
971
972 key = Tcl_GetString(objv[3]);
973 vPtr = ns_malloc(sizeof *vPtr);
974 value = Tcl_GetStringFromObj(objv[4], &vPtr->length);
975 vPtr->value = ns_malloc((size_t) vPtr->length);
976 memcpy(vPtr->value, value, (size_t) vPtr->length);
977
978 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheLock">Ns_CacheLock</a>(cache);
979
980 ePtr = <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheCreateEntry">Ns_CacheCreateEntry</a>(cache, key, &new);
981 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheSetValueSz">Ns_CacheSetValueSz</a>(ePtr, vPtr, (size_t) vPtr->length);
982
983 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheUnlock">Ns_CacheUnlock</a>(cache);
984
985 return TCL_OK;
986 }
987
988 /*
989 *----------------------------------------------------------------------
990 *
991 * <a href="/cvs/aolserver/nscache/tclcache.c#A_GlobalCacheIncrCmd">GlobalCacheIncrCmd</a> --
992 *
993 * Increases the value by specified key in the cache, creates new entry
994 * if does not exist
995 *
996 * Results:
997 * TCL_OK
998 *
999 * Side effects:
1000 * None.
1001 *
1002 *----------------------------------------------------------------------
1003 */
1004
1005 static int
1006 <a href="/cvs/aolserver/nscache/tclcache.c#A_GlobalCacheIncrCmd">GlobalCacheIncrCmd</a>(Ns_Cache *cache, int needsLocking, Tcl_Interp *interp,
1007 int objc, Tcl_Obj * CONST objv[])
1008 {
1009 int incr = 1;
1010 char buf[20];
1011 Ns_Entry *ePtr;
1012 GlobalValue *vPtr;
1013
1014 if (objc < 4) {
1015 Tcl_AppendResult(interp, "wrong # args: should be \"",
1016 Tcl_GetString(objv[0]), " ",
1017 Tcl_GetString(objv[1]), " cache key ?value?\"", NULL);
1018 return TCL_ERROR;
1019 }
1020
1021 if (objc > 4 && Tcl_GetIntFromObj(interp,objv[4],&incr) != TCL_OK) {
1022 return TCL_ERROR;
1023 }
1024
1025 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheLock">Ns_CacheLock</a>(cache);
1026
1027 ePtr = <a href="/cvs/aolserver/nscache/tclcache.c#A_GetGlobalEntry">GetGlobalEntry</a>(cache, Tcl_GetString(objv[3]), 1);
1028 vPtr = (GlobalValue *)<a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheGetValue">Ns_CacheGetValue</a>(ePtr);
1029 sprintf(buf,"%d",(vPtr->value ? atoi(vPtr->value) : 0) + incr);
1030 ns_free(vPtr->value);
1031 vPtr->value = ns_strdup(buf);
1032 vPtr->length = strlen(buf);
1033
1034 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheUnlock">Ns_CacheUnlock</a>(cache);
1035
1036 Tcl_SetStringObj(Tcl_GetObjResult(interp), vPtr->value, vPtr->length);
1037 return TCL_OK;
1038 }
1039
1040 /*
1041 *----------------------------------------------------------------------
1042 *
1043 * <a href="/cvs/aolserver/nscache/tclcache.c#A_ThreadCacheGetCmd">ThreadCacheGetCmd</a> --
1044 *
1045 * Get a value from the cache given a key.
1046 *
1047 * Results:
1048 * TCL result.
1049 *
1050 * Side effects:
1051 * None.
1052 *
1053 *----------------------------------------------------------------------
1054 */
1055
1056 static int
1057 <a href="/cvs/aolserver/nscache/tclcache.c#A_ThreadCacheGetCmd">ThreadCacheGetCmd</a>(Ns_Cache *cache, int needsLocking, Tcl_Interp *interp,
1058 int objc, Tcl_Obj * CONST objv[])
1059 {
1060 char *key;
1061 char *varname;
1062 Tcl_Obj *resultPtr;
1063 Ns_Entry *ePtr;
1064 Tcl_Obj *vPtr;
1065 int status = TCL_OK;
1066
1067 if (objc == 4) {
1068 varname = NULL;
1069 }
1070
1071 else if (objc == 5) {
1072 varname = Tcl_GetString(objv[4]);
1073 }
1074
1075 else {
1076 Tcl_AppendResult(interp, "wrong # args: should be \"",
1077 Tcl_GetString(objv[0]), " ",
1078 Tcl_GetString(objv[1]), " cache key ?varname?\"", NULL);
1079 return TCL_ERROR;
1080 }
1081
1082 resultPtr = Tcl_GetObjResult(interp);
1083 key = Tcl_GetString(objv[3]);
1084
1085 ePtr = <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheFindEntry">Ns_CacheFindEntry</a>(cache, key);
1086
1087 if (ePtr == NULL) {
1088
1089 if (varname == NULL) {
1090 Tcl_AppendStringsToObj(resultPtr, "no such key: ", key, NULL);
1091 status = TCL_ERROR;
1092 } else {
1093 Tcl_SetBooleanObj(resultPtr, 0);
1094 }
1095
1096 } else {
1097
1098 vPtr = (Tcl_Obj *) <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheGetValue">Ns_CacheGetValue</a>(ePtr);
1099 if (varname == NULL) {
1100 Tcl_SetObjResult(interp, vPtr);
1101 } else {
1102 Tcl_SetBooleanObj(resultPtr, 1);
1103
1104 if (Tcl_SetVar2Ex(interp, varname, NULL, vPtr,
1105 TCL_LEAVE_ERR_MSG) == NULL)
1106 {
1107 status = TCL_ERROR;
1108 }
1109 }
1110
1111 }
1112
1113 return status;
1114 }
1115
1116 /*
1117 *----------------------------------------------------------------------
1118 *
1119 * <a href="/cvs/aolserver/nscache/tclcache.c#A_ThreadCacheEvalCmd">ThreadCacheEvalCmd</a> --
1120 *
1121 * Get a value from the cache given a key. If the key is not in
1122 * the cache, evaluate the code block and store its result as the
1123 * value for the key.
1124 *
1125 * Results:
1126 * TCL result.
1127 *
1128 * Side effects:
1129 * None.
1130 *
1131 *----------------------------------------------------------------------
1132 */
1133
1134 static int
1135 <a href="/cvs/aolserver/nscache/tclcache.c#A_ThreadCacheEvalCmd">ThreadCacheEvalCmd</a>(Ns_Cache *cache, int needsLocking, Tcl_Interp *interp,
1136 int objc, Tcl_Obj * CONST objv[])
1137 {
1138 Ns_Entry *ePtr;
1139 Tcl_Obj *resultPtr;
1140 int status;
1141 int new;
1142 int length;
1143
1144 if (objc != 5) {
1145 Tcl_AppendResult(interp, "wrong # args: should be \"",
1146 Tcl_GetString(objv[0]), " ",
1147 Tcl_GetString(objv[1]), " cache key code\"", NULL);
1148 return TCL_ERROR;
1149 }
1150
1151 ePtr = <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheCreateEntry">Ns_CacheCreateEntry</a>(cache, Tcl_GetString(objv[3]), &new);
1152
1153 if (new) {
1154
1155 status = Tcl_EvalObjEx(interp, objv[4], 0);
1156
1157 if (status == TCL_OK || status == TCL_RETURN) {
1158 resultPtr = Tcl_GetObjResult(interp);
1159 Tcl_GetStringFromObj(resultPtr, &length);
1160 Tcl_IncrRefCount(resultPtr);
1161 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheSetValueSz">Ns_CacheSetValueSz</a>(ePtr, resultPtr, (size_t) length);
1162 status = TCL_OK;
1163 }
1164
1165 else {
1166 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheDeleteEntry">Ns_CacheDeleteEntry</a>(ePtr);
1167 }
1168
1169 } else {
1170
1171 status = TCL_OK;
1172 Tcl_SetObjResult(interp, (Tcl_Obj *) <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheGetValue">Ns_CacheGetValue</a>(ePtr));
1173
1174 }
1175
1176 return status;
1177 }
1178
1179 /*
1180 *----------------------------------------------------------------------
1181 *
1182 * <a href="/cvs/aolserver/nscache/tclcache.c#A_ThreadCacheSetCmd">ThreadCacheSetCmd</a> --
1183 *
1184 * Store the key/value pair in the cache, flushing any previous
1185 * value for the key.
1186 *
1187 * Results:
1188 * TCL_OK
1189 *
1190 * Side effects:
1191 * None.
1192 *
1193 *----------------------------------------------------------------------
1194 */
1195
1196 static int
1197 <a href="/cvs/aolserver/nscache/tclcache.c#A_ThreadCacheSetCmd">ThreadCacheSetCmd</a>(Ns_Cache *cache, int needsLocking, Tcl_Interp *interp,
1198 int objc, Tcl_Obj * CONST objv[])
1199 {
1200 Tcl_Obj *value;
1201 int length;
1202 Ns_Entry *ePtr;
1203 int new;
1204
1205 if (objc != 5) {
1206 Tcl_AppendResult(interp, "wrong # args: should be \"",
1207 Tcl_GetString(objv[0]), " ",
1208 Tcl_GetString(objv[1]), " cache key value\"", NULL);
1209 return TCL_ERROR;
1210 }
1211
1212 value = objv[4];
1213
1214 ePtr = <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheCreateEntry">Ns_CacheCreateEntry</a>(cache, Tcl_GetString(objv[3]), &new);
1215 Tcl_GetStringFromObj(value, &length);
1216 Tcl_IncrRefCount(value);
1217 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheSetValueSz">Ns_CacheSetValueSz</a>(ePtr, value, (size_t) length);
1218
1219 return TCL_OK;
1220 }
1221
1222 /*
1223 *----------------------------------------------------------------------
1224 *
1225 * <a href="/cvs/aolserver/nscache/tclcache.c#A_ThreadCacheIncrCmd">ThreadCacheIncrCmd</a> --
1226 *
1227 * Increases the value by specified key in the cache, creates new entry
1228 * if does not exist
1229 *
1230 * Results:
1231 * TCL_OK
1232 *
1233 * Side effects:
1234 * None.
1235 *
1236 *----------------------------------------------------------------------
1237 */
1238
1239 static int
1240 <a href="/cvs/aolserver/nscache/tclcache.c#A_ThreadCacheIncrCmd">ThreadCacheIncrCmd</a>(Ns_Cache *cache, int needsLocking, Tcl_Interp *interp,
1241 int objc, Tcl_Obj * CONST objv[])
1242 {
1243 int incr = 1;
1244 int length;
1245 int new;
1246 int iVal;
1247 Tcl_Obj *oPtr;
1248 Ns_Entry *ePtr;
1249
1250 if (objc < 4) {
1251 Tcl_AppendResult(interp, "wrong # args: should be \"",
1252 Tcl_GetString(objv[0]), " ",
1253 Tcl_GetString(objv[1]), " cache key ?value?\"", NULL);
1254 return TCL_ERROR;
1255 }
1256
1257 if (objc > 4 && Tcl_GetIntFromObj(interp,objv[4],&incr) != TCL_OK) {
1258 return TCL_ERROR;
1259 }
1260
1261 ePtr = <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheCreateEntry">Ns_CacheCreateEntry</a>(cache,Tcl_GetString(objv[3]),&new);
1262 if (new) {
1263 oPtr = Tcl_NewLongObj(1);
1264 Tcl_IncrRefCount(oPtr);
1265 Tcl_GetStringFromObj(oPtr, &length);
1266 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheSetValueSz">Ns_CacheSetValueSz</a>(ePtr, oPtr, (size_t) length);
1267 } else {
1268 oPtr = (Tcl_Obj *)<a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheGetValue">Ns_CacheGetValue</a>(ePtr);
1269 if (Tcl_GetIntFromObj(interp,oPtr,&iVal) != TCL_OK) return TCL_ERROR;
1270 Tcl_SetLongObj(oPtr, (iVal + incr));
1271 }
1272
1273 Tcl_SetObjResult(interp, oPtr);
1274 return TCL_OK;
1275 }
1276
1277 /*
1278 *----------------------------------------------------------------------
1279 *
1280 * <a href="/cvs/aolserver/nscache/tclcache.c#A_NsTclCacheCmd">NsTclCacheCmd</a> --
1281 *
1282 * Execute a Tcl ns_cache command.
1283 *
1284 * Results:
1285 * Tcl result.
1286 *
1287 * Side effects:
1288 * Depends on subcommand.
1289 *
1290 *----------------------------------------------------------------------
1291 */
1292
1293 static int
1294 <a href="/cvs/aolserver/nscache/tclcache.c#A_NsTclCacheCmd">NsTclCacheCmd</a>(ClientData arg, Tcl_Interp *interp, int objc,
1295 Tcl_Obj * CONST objv[])
1296 {
1297 char *cmd;
1298 TclCache *cache;
1299 int needsLocking;
1300 TclCacheCmdProc *procPtr = NULL;
1301 Server *servPtr = arg;
1302
1303 if (objc < 2) {
1304 Tcl_AppendResult(interp, "usage: ", Tcl_GetString(objv[0]),
1305 " subcommand args\n where subcommand is one of: ",
1306 "create eval flush get names set", NULL);
1307 return TCL_ERROR;
1308 }
1309
1310 cmd = Tcl_GetString(objv[1]);
1311
1312 if (STREQ(cmd, "create")) {
1313 return <a href="/cvs/aolserver/nscache/tclcache.c#A_CreateCmd">CreateCmd</a>(interp, servPtr, objc, objv);
1314 }
1315
1316 else if (
1317 STREQ(cmd, "eval")
1318 || STREQ(cmd, "flush")
1319 || STREQ(cmd, "get")
1320 || STREQ(cmd, "names")
1321 || STREQ(cmd, "set")
1322 || STREQ(cmd, "incr")
1323 ) {
1324 if (objc < 3) {
1325 Tcl_AppendResult(interp, "missing cache name for ",
1326 Tcl_GetString(objv[0]), " ", Tcl_GetString(objv[1]),
1327 " command", NULL);
1328 return TCL_ERROR;
1329 }
1330
1331 cache = <a href="/cvs/aolserver/nscache/tclcache.c#A_TclCacheFind">TclCacheFind</a>(servPtr, Tcl_GetString(objv[2]), &needsLocking);
1332 if (cache == NULL) {
1333 Tcl_AppendResult(interp, "no such cache: ",
1334 Tcl_GetString(objv[2]), NULL);
1335 return TCL_ERROR;
1336 }
1337
1338 switch (*cmd) {
1339 case 'e': procPtr = cache->evalPtr; break;
1340 case 'f': procPtr = cache->flushPtr; break;
1341 case 'g': procPtr = cache->getPtr; break;
1342 case 'n': procPtr = cache->namesPtr; break;
1343 case 's': procPtr = cache->setPtr; break;
1344 case 'i': procPtr = cache->incrPtr; break;
1345 }
1346
1347 return (*procPtr)(cache->nscache, needsLocking, interp, objc, objv);
1348 }
1349
1350 Tcl_AppendResult(interp, "unknown ", Tcl_GetString(objv[0]),
1351 " subcommand \"", Tcl_GetString(objv[1]), "\"", NULL);
1352 return TCL_ERROR;
1353 }
1354
1355 /*
1356 *----------------------------------------------------------------------
1357 *
1358 * <a href="/cvs/aolserver/nscache/tclcache.c#A_GlobalValueFree">GlobalValueFree</a> --
1359 *
1360 * Free a GlobalValue. If vPtr->value == NULL, then the value is
1361 * incomplete and some thread is still computing it. Simply set
1362 * the flushed flag, but don't free the GlobalValue, so that thread
1363 * can discover that its entry has been flushed. If vPtr->value !=
1364 * NULL, then the value is complete and we can free the GlobalValue.
1365 *
1366 * Results:
1367 * None.
1368 *
1369 * Side effects:
1370 * Either frees vPtr or sets vPtr->tid = 0.
1371 *
1372 *----------------------------------------------------------------------
1373 */
1374
1375 static void
1376 <a href="/cvs/aolserver/nscache/tclcache.c#A_GlobalValueFree">GlobalValueFree</a>(void *p)
1377 {
1378 GlobalValue *vPtr = p;
1379
1380 if (vPtr->value == NULL) {
1381 vPtr->flushed = 1;
1382 }
1383
1384 else {
1385 ns_free(vPtr->value);
1386 ns_free(vPtr);
1387 }
1388 }
1389
1390 /*
1391 *----------------------------------------------------------------------
1392 *
1393 * <a href="/cvs/aolserver/nscache/tclcache.c#A_ThreadValueFree">ThreadValueFree</a> --
1394 *
1395 * Free a value in a thread-private cache. Such values are always
1396 * Tcl_Obj pointers.
1397 *
1398 * Results:
1399 * None.
1400 *
1401 * Side effects:
1402 * Decrements a Tcl_Obj reference count and possibly frees the
1403 * object.
1404 *
1405 *----------------------------------------------------------------------
1406 */
1407
1408 static void
1409 <a href="/cvs/aolserver/nscache/tclcache.c#A_ThreadValueFree">ThreadValueFree</a>(void *p)
1410 {
1411 Tcl_Obj *oPtr = (Tcl_Obj *)p;
1412
1413 Tcl_DecrRefCount(oPtr);
1414 }
1415
1416 /*
1417 *----------------------------------------------------------------------
1418 *
1419 * <a href="/cvs/aolserver/nscache/tclcache.c#A_CleanupThreadCache">CleanupThreadCache</a> --
1420 *
1421 * Delete a thread cache entirely.
1422 *
1423 * Results:
1424 * None.
1425 *
1426 * Side effects:
1427 * None.
1428 *
1429 *----------------------------------------------------------------------
1430 */
1431
1432 static void
1433 <a href="/cvs/aolserver/nscache/tclcache.c#A_CleanupThreadCache">CleanupThreadCache</a>(void *p)
1434 {
1435 TclCache *cache = (TclCache *) p;
1436
1437 <a href="/cvs/aolserver/aolserver/nsd/cache.c#A_Ns_CacheDestroy">Ns_CacheDestroy</a>(cache->nscache);
1438 ns_free(cache);
1439 }
1440
1441 /*
1442 *----------------------------------------------------------------------
1443 *
1444 * <a href="/cvs/aolserver/nscache/tclcache.c#A_CacheFind">CacheFind</a> --
1445 *
1446 * Locates the cache for a virtual-server.
1447 *
1448 * Results:
1449 * The cache descriptor or NULL if no cache found.
1450 *
1451 * Side effects:
1452 * Per-thread cache may be created.
1453 *
1454 *----------------------------------------------------------------------
1455 */
1456
1457 static TclCache *
1458 <a href="/cvs/aolserver/nscache/tclcache.c#A_CacheFind">CacheFind</a>(Server *servPtr, char *name, int *needsLockingPtr)
1459 {
1460 Tcl_HashEntry *hPtr;
1461 TclCacheInfo *info;
1462 TclCache *cache = NULL;
1463
1464 Ns_MutexLock(&servPtr->lock);
1465 hPtr = Tcl_FindHashEntry(&servPtr->tclCaches, name);
1466 if (hPtr != NULL) {
1467 info = (TclCacheInfo *) Tcl_GetHashValue(hPtr);
1468 if (info->globalCache != NULL) {
1469 cache = info->globalCache;
1470 *needsLockingPtr = NS_TRUE;
1471 } else {
1472 cache = <a href="/cvs/aolserver/nscache/tclcache.c#A_GetThreadCache">GetThreadCache</a>(name, info);
1473 *needsLockingPtr = NS_FALSE;
1474 }
1475 }
1476 Ns_MutexUnlock(&servPtr->lock);
1477
1478 return cache;
1479 }
1480
1481