fixed parsing for science direct html with more than one <a href=> per one <tr>
[webpac] / openisis / lsv.h
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 */