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 |
#ifndef LSV_H |
23 |
|
24 |
/* |
25 |
$Id: lsv.h,v 1.11 2003/06/03 17:09:20 kripke Exp $ |
26 |
OpenIsis server |
27 |
*/ |
28 |
|
29 |
#ifdef _REENTRANT /* it's really the wrong flag, but *sigh* */ |
30 |
#define LSVTHR |
31 |
#endif |
32 |
|
33 |
#ifdef LSVTHR |
34 |
#include <pthread.h> /* else the work is done by the receiver */ |
35 |
#endif |
36 |
|
37 |
|
38 |
#include "loi.h" |
39 |
#include "lio.h" |
40 |
#include "lses.h" |
41 |
|
42 |
|
43 |
/** network service |
44 |
|
45 |
RECV: loop in receiver thread |
46 |
- loop selecting on all connections |
47 |
- dequeue connections from recv queue, clear BUSY |
48 |
- for every available connection: |
49 |
- if request is new (no input so far), |
50 |
prepare req with peer header, preset default flags |
51 |
- read input (which may clear the LIO_IN flag on EOF) |
52 |
- call proto to extract input |
53 |
proto calls check (if any) to preprocess each piece of input |
54 |
- if done, set BUSY, pass to dispatcher (via queue or in same thread) |
55 |
|
56 |
DISP: the one and only session master (in separate thread, if multiple recv) |
57 |
- no input after this point, the req is considered read-only |
58 |
any data on connection is considered an error (i.e. no pipelining) |
59 |
- if request contains a SID header, find or create session. |
60 |
if session is busy, enqueue to session's wait queue |
61 |
- enqueue to work queue |
62 |
|
63 |
WORK: (in worker thread) |
64 |
- once a worker thread dequeued a request, it calls process function |
65 |
this may add fields to response and/or write to output stream |
66 |
- before output buffer is flushed first time, |
67 |
it is set aside and proto is called to output the response |
68 |
- after process is done, the request is marked in flush phase: |
69 |
the req is not accessed after this point, |
70 |
the output is flushed and the response freed |
71 |
- enqueue to recv queue |
72 |
|
73 |
|
74 |
events in connection lifetime: |
75 |
- accept: |
76 |
if the socket hasn't been used so far, a new connection is created. |
77 |
an existing connection is reused. |
78 |
The connection object may still be in use by a worker. |
79 |
Since the socket file id is reused, the former socket with the |
80 |
same fid must have been closed, and the LIO_INOUT flags |
81 |
must have been cleared, so lio_write on that old lio file id will fail. |
82 |
The connection is marked as new and, if not in use by a worker, |
83 |
entered into the receive queue. |
84 |
- dequeue from receive queue: |
85 |
if the connection is marked new, |
86 |
it is prepared and added to the select set. |
87 |
else, if it was closed, it is removed from the select set. |
88 |
- read events: |
89 |
if the connection is in use, that is, a previous request hasn't yet |
90 |
entered the flush phase, there is an attempt to pipeline. |
91 |
while this is considered an error, for robustness it's handled: |
92 |
the connection is marked pipeline and the socket is cleared |
93 |
from the select set, to be reenabled later. |
94 |
Once the connection is idle, input is read until the protocol |
95 |
decides on a complete request. Excess data (immediate pipelining) |
96 |
is considered an error. |
97 |
*/ |
98 |
|
99 |
/* common header tags -- actually negative tags are used */ |
100 |
enum { |
101 |
/* nonstandard */ |
102 |
LSV_TEXT, /* +- 0: a small, inlined untyped or text/plain body */ |
103 |
LSV_RID, /* row id, a.k.a MFN */ |
104 |
LSV_SID, /* session id */ |
105 |
LSV_PEER, /* network peer ("remote host") */ |
106 |
LSV_TIME, /* GTF + millis */ |
107 |
LSV_ATTACH, /* wrapped-up attachment, TBD */ |
108 |
/* MIME basics */ |
109 |
LSV_CTYPE, |
110 |
/* HTTP: CGI/servlet */ |
111 |
LSV_URI, |
112 |
LSV_QUERY |
113 |
}; |
114 |
|
115 |
enum { |
116 |
#ifdef LSVTHR |
117 |
LSV_NUMWRK = 8, |
118 |
#else |
119 |
LSV_NUMWRK = 1, |
120 |
#endif |
121 |
LSV_BUFSIZ = 0x04000, /* 16384 a.k.a. 16K */ |
122 |
LSV_BUFMSK = 0x03fff /* mask buf lengths */ |
123 |
}; |
124 |
|
125 |
typedef struct Que { |
126 |
struct Con *head; |
127 |
struct Con *tail; |
128 |
int len; |
129 |
} Que; |
130 |
|
131 |
/* queue with pool of workers waiting */ |
132 |
typedef struct Pool { |
133 |
Que que; |
134 |
#ifdef LSVTHR |
135 |
struct Wrk *wait; /* stack */ |
136 |
#endif |
137 |
} Pool; |
138 |
|
139 |
typedef struct Wrk { |
140 |
#ifdef LSVTHR |
141 |
pthread_t thr; |
142 |
#endif |
143 |
unsigned id; |
144 |
struct Srv *srv; |
145 |
struct Wrk *nxt; |
146 |
Session ses; |
147 |
#ifdef LSVTHR |
148 |
pthread_cond_t todo; /* work condition waited for by workers */ |
149 |
#endif |
150 |
/* stats */ |
151 |
struct Con *cur; /* current job */ |
152 |
int jobs; |
153 |
int waits; |
154 |
} Wrk; |
155 |
|
156 |
typedef struct Srv { |
157 |
/* |
158 |
the protocol stream method |
159 |
- with LIO_SPUSH, input is pushed to request (len 0 indicates EOF) |
160 |
return 0=more, >0=done, <0=error |
161 |
- on LIO_SFLUSH, prt must convert output buffer to flt |
162 |
- on LIO_SCLOSE, prt must flush and close answer |
163 |
*/ |
164 |
int (*prt) ( Ios*, int op ); |
165 |
/* |
166 |
the application |
167 |
- with task APPARG (called by prt for each field): |
168 |
check (and typically modify) last field extracted by prt |
169 |
return 0=more, >0=done, <0=error |
170 |
- with task APPGOT (after request is complete): |
171 |
check request, add -LSV_SID field, if needed |
172 |
(e.g. to extract from an URL or cookie) |
173 |
- with task APPRUN (0): |
174 |
process request |
175 |
*/ |
176 |
int (*app) ( struct Con*, int task ); |
177 |
Fdt *fdt; /* field def */ |
178 |
int flg; /* flags */ |
179 |
unsigned sto; /* config: session timeout (seconds) */ |
180 |
unsigned nwr; /* config: #workers (<= LSV_NUMWRK) */ |
181 |
Session ses; /* usually the default session */ |
182 |
Tm tim; /* tim of last turn */ |
183 |
char gtm[20]; /* generalized time (actually 18 digits) */ |
184 |
Wrk wrk[LSV_NUMWRK]; |
185 |
/* |
186 |
single receiver model |
187 |
*/ |
188 |
int lsn; /* listening socket */ |
189 |
Que recv; /* enq by worker, deq by receiver */ |
190 |
Pool main; /* enq by dispatcher, deq by workers */ |
191 |
#ifdef LSVTHR |
192 |
Pool pool; /* enq by dispatcher, deq by workers */ |
193 |
pthread_t rcv; /* the receiver thread */ |
194 |
pthread_mutex_t mut; /* single mutex held by recv/disp while not in select */ |
195 |
int pip[2]; /* pipe for pending events */ |
196 |
#endif |
197 |
/* stats */ |
198 |
int plen; /* length of pool */ |
199 |
int jobs; /* total #jobs */ |
200 |
int conn; /* total #conn */ |
201 |
int turn; /* total #turn */ |
202 |
float wlen; /* cumulated length of work queue (on each turn) */ |
203 |
float busy; /* cumulated # of active workers (on each turn) */ |
204 |
} Srv; |
205 |
|
206 |
enum { /* server flags */ |
207 |
LSV_CONSES = 0x01, /* session bound to connection */ |
208 |
LSV_WRKSES = 0x02, /* session bound to worker */ |
209 |
LSV_SHUTDN = 0x100 /* server is shutting down */ |
210 |
}; |
211 |
enum { |
212 |
/* called in worker thread: */ |
213 |
LSV_APPRUN, /* app called to process request */ |
214 |
LSV_APPINI, /* app called to initialise non-main thread (no con) */ |
215 |
LSV_APPFIN, /* app called to finalize non-main thread (no con) */ |
216 |
/* called in receiver thread: */ |
217 |
LSV_APPARG, /* app called to check parameter */ |
218 |
LSV_APPGOT, /* app called after all input */ |
219 |
LSV_APPSES /* app called on new session */ |
220 |
}; |
221 |
enum { /* connection pending state */ |
222 |
LSV_PDGNON, /* new connection pending */ |
223 |
LSV_PDGNEW, /* new connection pending */ |
224 |
LSV_PDGRED, /* ready to read pending */ |
225 |
LSV_PDGEOF /* EOF pending */ |
226 |
/* when adding, keep array of names in sync */ |
227 |
}; |
228 |
enum { /* connection processing stage */ |
229 |
LSV_STGNEW, /* connection needs to be setup */ |
230 |
LSV_STGCON, /* connected, no request on the way */ |
231 |
LSV_STGINP, /* reading input */ |
232 |
LSV_STGSES, /* waiting for session */ |
233 |
LSV_STGWRK, /* queued for work */ |
234 |
/* set by worker: */ |
235 |
LSV_STGRUN, /* dequeued */ |
236 |
LSV_STGCOM, /* commited (output has started) */ |
237 |
LSV_STGDON, /* done processing, flushing output */ |
238 |
LSV_STGRET /* returning (queued to recv) */ |
239 |
/* when adding, keep array of names in sync */ |
240 |
}; |
241 |
|
242 |
typedef struct Con { |
243 |
Ios ios; /* raw output */ |
244 |
Buf flt; /* protocol filtered output */ |
245 |
const Srv *srv; |
246 |
struct Con *nxt; |
247 |
unsigned char stg; /* processing stage (guarded by mutex) */ |
248 |
unsigned char pdg; /* pending flags set by receiver only */ |
249 |
unsigned char grp; /* thread group (0=main) set by receiver app calls */ |
250 |
unsigned char bin; /* client requested binary mode */ |
251 |
int prt; /* for free use by prt, 0 init */ |
252 |
int app; /* for free use by app, 0 init */ |
253 |
int host; |
254 |
char nam[64]; /* 123.123.123.123:123456 for IPv4 */ |
255 |
Session ses; |
256 |
Rec *req; /* request -- owned by srv->ses */ |
257 |
Tm tim; /* time when the request was scheduled */ |
258 |
/* Rec *res; response -- owned by ses */ |
259 |
int con; /* connection counter */ |
260 |
} Con; |
261 |
|
262 |
extern Wrk *svCur (); |
263 |
extern int svRun ( Srv *srv, const char *addr ); |
264 |
/* the plain protocol */ |
265 |
extern int svPlain ( Ios *s, int op ); |
266 |
extern int svEcho ( Con *c, int task ); |
267 |
|
268 |
#define LSV_H |
269 |
#endif /* LSV_H */ |