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
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.
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.
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
20 see README for more information
24 $Id: lses.c,v 1.18 2003/05/26 10:55:10 kripke Exp $
25 implementation of general db access functions.
29 #include <string.h> /* memset */
33 # define WIN32_LEAN_AND_MEAN
34 # define NONAMELESSUNION
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 )
49 /* ************************************************************
62 /* ************************************************************
66 /* ************************************************************
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 )
74 static SesI cses = { /* the default session */
78 { stdio, stdio+1, stdio+2 },
80 0, 0, /* nxt, accnt */
81 {0},{0},{0}, /* times */
86 static SesI *tab[ LSES_MAX ] = {
89 static Ses *htab[ LSES_MAX ];
91 static const char oops[] = "out of memory\n";
94 Session ses = &cses.h;
96 int openisis_threaded = 42;
97 static pthread_key_t seskey;
100 /* ************************************************************
104 static void *memordie ( int size )
106 void *p = malloc( size );
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 */
116 /* ************************************************************
120 void lses_init () /* called from openIsisInit */
123 pthread_key_create( &seskey, 0 ); /* TODO: use ses destr func */
124 pthread_setspecific( seskey, &cses.h );
129 void lses_fini () /* called from openIsisFini */
132 /* lio_write( &lio_out, "fini time\n", 9 ); */
135 for ( i=0; i<3; i++ )
136 if ( tab[s]->h.io[i] )
137 LIO_CLOSE( tab[s]->h.io[i] );
141 int lses_open ( Session s, const char *name, int flags, SFunc *type )
144 const char *p = name;
145 lio_sfunc *func = type ? (lio_sfunc*)type : lio_stdio;
148 while ( '0' <= *p && *p <= '9' )
149 fd = 10*fd + *p++ - '0';
150 if ( '<' != *p && '>' != *p )
151 p = name; /* forget it */
153 if ( name == p && '>' == *p ) /* no fd given, > defaults to 1 */
155 flags |= '<' == *p ? LIO_RD : LIO_WR;
158 if ( p == name ) { /* no fd given, find one */
159 for ( fd=0; s->io[fd]; )
160 if ( LSES_FILE_MAX == ++fd )
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 )
168 s->io[fd] = (Ios*)mAlloc( func( 0, LIO_SSIZE ) );
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 );
179 /* ************************************************************
187 if ( ! (ses = (Ses*)pthread_getspecific( seskey )) )
188 pthread_setspecific( seskey, ses = cSession( 0 ) );
193 extern void sSet ( Ses *s )
198 pthread_setspecific( seskey, s );
203 Ses *cOpen ( Rec *args )
208 if ( args ) { /* add args */
209 /* TODO: merge args */
210 cses.h.prop = rDup( args, -1, 0 );
216 Ses *cSession ( Rec *args )
221 /** XXX unless we actually free sessions,
222 we should start checking with maxid
226 if ( LSES_MAX == ++id )
230 sesi = tab[id] = (SesI*)malloc( sizeof(SesI) );
231 memset( sesi, 0, sizeof(SesI) );
234 s->hash = -1; /* not hashed (hash is non-negative) */
235 s->prop = args ? rDup( args, -1, 0 ) : 0;
238 lses_open( s, "2>&2", 0, lio_stdio );
243 void *mAlloc ( int size )
245 void *p = memordie( size );
251 void mFree ( void *mem )
258 void *mDup ( const void *str, int sz )
260 void *m = memordie( 0<=sz ? sz : (sz = strlen( str ) + 1) );
261 memcpy( m, str, sz );
266 int sOpen ( const char *name, int flags, SFunc *type )
269 return lses_open( ses, name, flags, type );
273 Ses *openIsisId2Session (int sid) {
274 if (0 > sid || LSES_MAX <= sid || 0 == tab[sid]) {
277 return &(tab[sid]->h);
278 } /* openIsisId2Session */
281 int openIsisSession2Id (Ses *s) {
286 } /* openIsisSession2Id */
289 Ses *cSesByName ( char *name, int nlen, Tm *now, Tm *expire )
299 if ( !(0xe0 & name[i]) )
301 h = lhash( name, nlen );
302 for ( s = htab[h & LSES_MSK]; s; s = s->nxt )
304 && !memcmp( name, s->name, nlen )
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!",
312 goto gotit; /* valid anyway */
316 /* didn't find by name */
317 if ( ! expire ) /* bad thing -- we're going to run out of sessions ... */
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 !? */
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 )
343 memset( s->name, 0, sizeof(s->name) );
344 memcpy( s->name, name, nlen );
346 s->nxt = htab[h & LSES_MSK];
347 htab[h & LSES_MSK] = s;
349 s->ctime.millis = s->mtime.millis = now ? now->millis : 0;
356 s->atime.millis = now ? now->millis : 0;