/[webpac]/trunk/openisis/lses.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/openisis/lses.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 239 - (show annotations)
Mon Mar 8 17:49:13 2004 UTC (20 years ago) by dpavlin
File MIME type: text/plain
File size: 8056 byte(s)
including openisis 0.9.0 into webpac tree

1 /*
2 openisis - an open implementation of the CDS/ISIS database
3 Version 0.8.x (patchlevel see file Version)
4 Copyright (C) 2001-2003 by Erik Grziwotz, erik@openisis.org
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 see README for more information
21 EOH */
22
23 /*
24 $Id: lses.c,v 1.18 2003/05/26 10:55:10 kripke Exp $
25 implementation of general db access functions.
26 */
27
28 #include <stdlib.h>
29 #include <string.h> /* memset */
30
31 #ifdef _REENTRANT
32 #ifdef WIN32
33 # define WIN32_LEAN_AND_MEAN
34 # define NONAMELESSUNION
35 # include <windows.h>
36 /* they call it "thread local storage" */
37 # define pthread_key_t int
38 # define pthread_key_create( pkey, func ) *(pkey) = TlsAlloc()
39 # define pthread_setspecific( key, val ) TlsSetValue( key, val )
40 # define pthread_getspecific( key ) TlsGetValue( key )
41 #else
42 # include <pthread.h>
43 #endif
44 #endif
45
46 #include "lses.h"
47
48
49 /* ************************************************************
50 private types
51 */
52 typedef struct {
53 Ses h;
54 /* int brk; */
55 } SesI;
56
57 enum {
58 LSES_MAX = 0x1000,
59 LSES_MSK = 0x0fff
60 };
61
62 /* ************************************************************
63 package data
64 */
65
66 /* ************************************************************
67 private data
68 */
69 static Ios stdio[3] = {
70 LIO_STDINITIALIZER( "&0", LIO_IN ),
71 LIO_STDINITIALIZER( "&1", LIO_OUT|1 ),
72 LIO_STDINITIALIZER( "&2", LIO_OUT|2 )
73 };
74 static SesI cses = { /* the default session */
75 {
76 0,
77 "",
78 { stdio, stdio+1, stdio+2 },
79 -1,
80 0, 0, /* nxt, accnt */
81 {0},{0},{0}, /* times */
82 0,0,0,0 /* state */
83 }
84 };
85
86 static SesI *tab[ LSES_MAX ] = {
87 &cses
88 };
89 static Ses *htab[ LSES_MAX ];
90 static int maxid;
91 static const char oops[] = "out of memory\n";
92
93 #ifndef _REENTRANT
94 Session ses = &cses.h;
95 #else
96 int openisis_threaded = 42;
97 static pthread_key_t seskey;
98 #endif
99
100 /* ************************************************************
101 private functions
102 */
103
104 static void *memordie ( int size )
105 {
106 void *p = malloc( size );
107 if ( p )
108 return p;
109 /* TODO: ask btree to release some cache */
110 lio_write( &lio_err, oops, sizeof(oops)-1 );
111 exit( 71/*EX_OSERR*/ ); /* exit handlers MUST NOT alloc memory */
112 return 0;
113 }
114
115
116 /* ************************************************************
117 package functions
118 */
119
120 void lses_init () /* called from openIsisInit */
121 {
122 #ifdef _REENTRANT
123 pthread_key_create( &seskey, 0 ); /* TODO: use ses destr func */
124 pthread_setspecific( seskey, &cses.h );
125 #endif
126 } /* lses_init */
127
128
129 void lses_fini () /* called from openIsisFini */
130 {
131 int i, s = LSES_MAX;
132 /* lio_write( &lio_out, "fini time\n", 9 ); */
133 while ( s-- )
134 if ( tab[s] )
135 for ( i=0; i<3; i++ )
136 if ( tab[s]->h.io[i] )
137 LIO_CLOSE( tab[s]->h.io[i] );
138 } /* lses_fini */
139
140
141 int lses_open ( Session s, const char *name, int flags, SFunc *type )
142 {
143 int fd = 0;
144 const char *p = name;
145 lio_sfunc *func = type ? (lio_sfunc*)type : lio_stdio;
146
147 /* check for i<> */
148 while ( '0' <= *p && *p <= '9' )
149 fd = 10*fd + *p++ - '0';
150 if ( '<' != *p && '>' != *p )
151 p = name; /* forget it */
152 else {
153 if ( name == p && '>' == *p ) /* no fd given, > defaults to 1 */
154 fd = 1;
155 flags |= '<' == *p ? LIO_RD : LIO_WR;
156 p++;
157 }
158 if ( p == name ) { /* no fd given, find one */
159 for ( fd=0; s->io[fd]; )
160 if ( LSES_FILE_MAX == ++fd )
161 return -ERR_NOMEM;
162 } else if ( s->io[fd] ) { /* close existing */
163 func( s->io[fd], LIO_SCLOSE );
164 /* don't kill the statics :) */
165 if ( s->io[fd] < stdio || s->io[fd] > stdio+2 )
166 mFree( s->io[fd] );
167 }
168 s->io[fd] = (Ios*)mAlloc( func( 0, LIO_SSIZE ) );
169 if ( ! s->io[fd] )
170 return -ERR_NOMEM;
171 s->io[fd]->func = func;
172 s->io[fd]->name = mDup( p, -1 );
173 s->io[fd]->file = flags;
174 return func( s->io[fd], LIO_SOPEN );
175 } /* lses_open */
176
177
178
179 /* ************************************************************
180 public functions
181 */
182
183 extern Ses *sGet ()
184 {
185 #ifdef _REENTRANT
186 Ses *ses;
187 if ( ! (ses = (Ses*)pthread_getspecific( seskey )) )
188 pthread_setspecific( seskey, ses = cSession( 0 ) );
189 #endif
190 return ses;
191 }
192
193 extern void sSet ( Ses *s )
194 {
195 #ifndef _REENTRANT
196 ses = s;
197 #else
198 pthread_setspecific( seskey, s );
199 #endif
200 }
201
202
203 Ses *cOpen ( Rec *args )
204 {
205 extern void linit();
206
207 linit();
208 if ( args ) { /* add args */
209 /* TODO: merge args */
210 cses.h.prop = rDup( args, -1, 0 );
211 }
212 return &cses.h;
213 } /* cOpen */
214
215
216 Ses *cSession ( Rec *args )
217 {
218 SesI *sesi = 0;
219 Ses *s = 0;
220 int id = 1;
221 /** XXX unless we actually free sessions,
222 we should start checking with maxid
223 or check for expiry
224 */
225 while ( tab[id] )
226 if ( LSES_MAX == ++id )
227 return 0;
228 if ( maxid < id )
229 maxid = id;
230 sesi = tab[id] = (SesI*)malloc( sizeof(SesI) );
231 memset( sesi, 0, sizeof(SesI) );
232 s = &sesi->h;
233 s->id = id;
234 s->hash = -1; /* not hashed (hash is non-negative) */
235 s->prop = args ? rDup( args, -1, 0 ) : 0;
236 /* check props */
237 /* open files */
238 lses_open( s, "2>&2", 0, lio_stdio );
239 return s;
240 } /* cSession */
241
242
243 void *mAlloc ( int size )
244 {
245 void *p = memordie( size );
246 memset(p, 0, size);
247 return p;
248 } /* mAlloc */
249
250
251 void mFree ( void *mem )
252 {
253 if ( mem )
254 free( mem );
255 } /* mFree */
256
257
258 void *mDup ( const void *str, int sz )
259 {
260 void *m = memordie( 0<=sz ? sz : (sz = strlen( str ) + 1) );
261 memcpy( m, str, sz );
262 return m;
263 } /* mDup */
264
265
266 int sOpen ( const char *name, int flags, SFunc *type )
267 {
268 SESDECL
269 return lses_open( ses, name, flags, type );
270 } /* sOpen */
271
272
273 Ses *openIsisId2Session (int sid) {
274 if (0 > sid || LSES_MAX <= sid || 0 == tab[sid]) {
275 return (Ses*)0;
276 }
277 return &(tab[sid]->h);
278 } /* openIsisId2Session */
279
280
281 int openIsisSession2Id (Ses *s) {
282 if (0 == s) {
283 return -1;
284 }
285 return s->id;
286 } /* openIsisSession2Id */
287
288
289 Ses *cSesByName ( char *name, int nlen, Tm *now, Tm *expire )
290 {
291 char tbuf[20];
292 int h,i;
293 Ses *s;
294 if ( nlen < 0 )
295 nlen = strlen(name);
296 if ( nlen > 63 )
297 nlen = 63;
298 for ( i=nlen; i--; )
299 if ( !(0xe0 & name[i]) )
300 name[i] = '_';
301 h = lhash( name, nlen );
302 for ( s = htab[h & LSES_MSK]; s; s = s->nxt )
303 if ( h == s->hash
304 && !memcmp( name, s->name, nlen )
305 && !s->name[nlen]
306 ) { /* match */
307 if ( !expire || s->atime.millis >= expire->millis )
308 goto gotit; /* valid */
309 if ( s->cur || s->que ) {
310 log_msg( LOG_WARN, "expired session %d %s still busy!",
311 s->id, s->name );
312 goto gotit; /* valid anyway */
313 }
314 goto refresh;
315 }
316 /* didn't find by name */
317 if ( ! expire ) /* bad thing -- we're going to run out of sessions ... */
318 i = maxid+1;
319 else /* check other expired */
320 for ( i=1; i<=maxid; i++ ) {
321 s = &tab[i]->h; /* sind wir heute defensiv ... */
322 if ( s && s->atime.millis < expire->millis
323 && s->atime.millis && 0 <= s->hash /* else is none of our biz */
324 && !s->cur && !s->que /* else is busy !? */
325 )
326 break;
327 }
328 if ( i > maxid ) {
329 s = cSession( 0 );
330 if ( ! s )
331 return 0;
332 } else /* got one */
333 log_msg( LOG_INFO, "reusing session %d '%s' atime %s",
334 s->id, s->name, s->atime.millis ? timeGtf(tbuf,&s->atime) : "-" );
335 if ( 0 <= s->hash ) { /* was hashed -- unlink */
336 Ses **spp = &htab[s->hash & LSES_MSK];
337 for ( ; *spp; spp = &(*spp)->nxt )
338 if ( s == *spp ) {
339 *spp = s->nxt;
340 break;
341 }
342 }
343 memset( s->name, 0, sizeof(s->name) );
344 memcpy( s->name, name, nlen );
345 s->hash = h;
346 s->nxt = htab[h & LSES_MSK];
347 htab[h & LSES_MSK] = s;
348 refresh:
349 s->ctime.millis = s->mtime.millis = now ? now->millis : 0;
350 s->accnt = 0;
351 if ( s->prop )
352 CLRREC( s->prop );
353 if ( s->res )
354 CLRREC( s->res );
355 gotit:
356 s->atime.millis = now ? now->millis : 0;
357 return s;
358 } /* cSesByName */

  ViewVC Help
Powered by ViewVC 1.1.26