1 |
dpavlin |
604 |
/* |
2 |
|
|
The Malete project - the Z39.2/Z39.50 database framework of OpenIsis. |
3 |
|
|
Version 0.9.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. |
14 |
|
|
See the GNU 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 PW_H |
23 |
|
|
|
24 |
|
|
/* |
25 |
|
|
$Id: pw.h,v 1.7 2004/03/16 22:17:52 kripke Exp $ |
26 |
|
|
interface of the Malete patchwork |
27 |
|
|
*/ |
28 |
|
|
|
29 |
|
|
#define PW_VERSION "0.9.9" |
30 |
|
|
|
31 |
|
|
|
32 |
|
|
#include "../core/core.h" |
33 |
|
|
|
34 |
|
|
|
35 |
|
|
typedef struct Obj Obj; |
36 |
|
|
|
37 |
|
|
|
38 |
|
|
/* ****************************************************************** */ |
39 |
|
|
/* */ |
40 |
|
|
/* HASH TABLE */ |
41 |
|
|
/* */ |
42 |
|
|
/* ****************************************************************** */ |
43 |
|
|
|
44 |
|
|
#define HEDEFKEYLEN 1 |
45 |
|
|
|
46 |
|
|
typedef struct HEntry HEntry; |
47 |
|
|
/* hmmm ... maybe this should become part of Obj */ |
48 |
|
|
struct HEntry { |
49 |
|
|
HEntry *nxt; |
50 |
|
|
Obj *obj; |
51 |
|
|
int hv; /* hash value of this entry */ |
52 |
|
|
#ifndef NDEBUG |
53 |
|
|
int dpt; |
54 |
|
|
#endif |
55 |
|
|
int len; |
56 |
|
|
char key[HEDEFKEYLEN]; /* not 0 terminated */ |
57 |
|
|
}; |
58 |
|
|
|
59 |
|
|
/* hmmm ... maybe this should become part of Struct */ |
60 |
|
|
typedef struct HTable { |
61 |
|
|
List *list; |
62 |
|
|
int mask; |
63 |
|
|
int nume; /* # of entries */ |
64 |
|
|
int dsize; /* # bytes of unlinked entries */ |
65 |
|
|
#ifndef NDEBUG |
66 |
|
|
int coll; /* # of collisions */ |
67 |
|
|
#endif |
68 |
|
|
} HTable; |
69 |
|
|
|
70 |
|
|
#define HSIZ(t) (-((t)->list->fld->tag)-1) /* number of buckets */ |
71 |
|
|
#define HSHIFT 1 /* rebuild factor: HSIZ(t) << HSHIFT */ |
72 |
|
|
#define HESIZ(he) (sizeof(HEntry)+(he)->len-HEDEFKEYLEN) /* entry size */ |
73 |
|
|
#define HINITIAL 32 /* initial # of buckets */ |
74 |
|
|
#define HMAXLOAD 75 /* max load factor */ |
75 |
|
|
#define HCURLOAD(t) ( (100*(t)->nume) / HSIZ(t) ) /* current load */ |
76 |
|
|
#define HSHRINKLOAD 25 /* shrink, if HCURLOAD(t) < HSHRINKLOAD */ |
77 |
|
|
#define HMAXFRAG 50 /* max fragmentation factor */ |
78 |
|
|
#define HCURFRAG(t) ( (100*((t)->dsize)) / LSIZ((t)->list) ) /* current frag */ |
79 |
|
|
|
80 |
|
|
|
81 |
|
|
extern HEntry* OPT_STDCALL hGet ( HTable *table, const char *key, int len ); |
82 |
|
|
extern HEntry* OPT_STDCALL hAdd ( HTable *table, const char *key, int len ); |
83 |
|
|
extern HEntry* OPT_STDCALL hSet ( HTable *t, const char *key, int len, Obj *o ); |
84 |
|
|
extern int OPT_STDCALL hDel ( HTable *table, const char *key, int len ); |
85 |
|
|
extern HTable* OPT_STDCALL hInit ( HTable *table, const char* header ); |
86 |
|
|
extern void OPT_STDCALL hFini ( HTable *table ); |
87 |
|
|
|
88 |
|
|
/* free al resources held by table */ |
89 |
|
|
#define HFREE( table ) do { \ |
90 |
|
|
hFini( (table) ); \ |
91 |
|
|
mFree( table ); \ |
92 |
|
|
} while (0) |
93 |
|
|
|
94 |
|
|
#ifndef NDEBUG |
95 |
|
|
/* debug statistics */ |
96 |
|
|
extern void OPT_STDCALL hstat ( HTable *table ); |
97 |
|
|
# define HSTAT(t) hstat(t); |
98 |
|
|
#else |
99 |
|
|
# define HSTAT(t) |
100 |
|
|
#endif |
101 |
|
|
|
102 |
|
|
|
103 |
|
|
|
104 |
|
|
/* ****************************************************************** */ |
105 |
|
|
/* */ |
106 |
|
|
/* OBJECTS AND MESSAGES */ |
107 |
|
|
/* */ |
108 |
|
|
/* ****************************************************************** */ |
109 |
|
|
|
110 |
|
|
typedef Fld * Msg; |
111 |
|
|
typedef struct Qry Qry; /* query implemented by dbo */ |
112 |
|
|
|
113 |
|
|
|
114 |
|
|
/* |
115 |
|
|
dispatch message "msg", starting at object obj. |
116 |
|
|
|
117 |
|
|
----------------------------------- |
118 |
|
|
Syntax and semantics of messages |
119 |
|
|
|
120 |
|
|
A message is basically an array of fields - usually of length 1. The leader |
121 |
|
|
of this array containes the messagename, denoting a method, and possibly |
122 |
|
|
options. The mesagename has to be given in the leader's primary value, the |
123 |
|
|
options in following subfields. Data to be processed is contained in the |
124 |
|
|
following fields - if any. The messagename may contain subobject specifiers, |
125 |
|
|
which have to be separated by a '.'. Besides this the evaluation of the |
126 |
|
|
given leader is solely in the responsibility of the method invoked. The |
127 |
|
|
message evaluation may change the given message. The significant length of a |
128 |
|
|
messagename may be limited to four bytes. A leader should not be longer |
129 |
|
|
than DEFBLKLEN bytes, though some messages may allow longer sizes. Some |
130 |
|
|
messagenames may use special characters denoting a special treatment of the |
131 |
|
|
given leader - thus such characters should not be used for ordinary |
132 |
|
|
messagenames. The result of the evaluation, if any, is always written to |
133 |
|
|
env.out. |
134 |
|
|
*/ |
135 |
|
|
typedef int OPT_STDCALL disp ( Obj *self, Msg msg ); |
136 |
|
|
|
137 |
|
|
/* |
138 |
|
|
the general form of an object |
139 |
|
|
send it a message using that->snd(msg) |
140 |
|
|
In general, snd must return <0 on error, >=0 else |
141 |
|
|
*/ |
142 |
|
|
struct Obj { |
143 |
|
|
disp *snd; /* method implementation */ |
144 |
|
|
}; |
145 |
|
|
/** |
146 |
|
|
base implementation for Obj handling pipes and such |
147 |
|
|
*/ |
148 |
|
|
extern int OPT_STDCALL oObj ( Obj *self, Msg msg ); |
149 |
|
|
|
150 |
|
|
|
151 |
|
|
typedef struct Struct Struct; |
152 |
|
|
|
153 |
|
|
typedef Obj* OPT_STDCALL factory ( Struct *self, const char *key, int len ); |
154 |
|
|
/* |
155 |
|
|
an object with variable number of childs |
156 |
|
|
*/ |
157 |
|
|
struct Struct { |
158 |
|
|
disp *snd; /* method implementation */ |
159 |
|
|
HTable *reg; /* child registry */ |
160 |
|
|
factory *fac; /* child factory */ |
161 |
|
|
}; |
162 |
|
|
/** |
163 |
|
|
base implementation for Struct handling child dispatching |
164 |
|
|
*/ |
165 |
|
|
extern int OPT_STDCALL oStruct ( Struct *self, Msg msg ); |
166 |
|
|
|
167 |
|
|
|
168 |
|
|
/** |
169 |
|
|
session -- the root object |
170 |
|
|
*/ |
171 |
|
|
typedef struct Ses { |
172 |
|
|
disp *snd; |
173 |
|
|
HTable *reg; /* main registry */ |
174 |
|
|
factory *fac; /* main factory */ |
175 |
|
|
Sink *out; /* main env.out for this session */ |
176 |
|
|
Sink *err; /* env.err for this session */ |
177 |
|
|
unsigned rid; /* last rid written */ |
178 |
|
|
Qry *qry; /* array of q queries */ |
179 |
|
|
lolo req; /* request counter */ |
180 |
|
|
/* options */ |
181 |
|
|
char *at; /* default target */ |
182 |
|
|
unsigned r; /* max # of records per read, 0 = unlimited */ |
183 |
|
|
unsigned q; /* max # of open query cursors != 0 */ |
184 |
|
|
unsigned s; /* max # of results in search set, 0 = unlimited */ |
185 |
|
|
} Ses; |
186 |
|
|
extern int OPT_STDCALL oSes ( Ses *self, Msg msg ); |
187 |
|
|
|
188 |
|
|
/* |
189 |
|
|
default main factory (i.e. for the session). |
190 |
|
|
scans the environment options for defined objects |
191 |
|
|
*/ |
192 |
|
|
extern Obj* OPT_STDCALL facMain ( Ses *self, const char *key, int len ); |
193 |
|
|
|
194 |
|
|
/* init session */ |
195 |
|
|
extern void sInit (Ses *s); |
196 |
|
|
|
197 |
|
|
|
198 |
|
|
extern Ses *ses; /* current session */ |
199 |
|
|
|
200 |
|
|
/* |
201 |
|
|
main dispatcher |
202 |
|
|
*/ |
203 |
|
|
#define dispatch( msg ) ses->snd((Obj*)ses, msg) |
204 |
|
|
|
205 |
|
|
|
206 |
|
|
/* |
207 |
|
|
object linked to a session on some remote server |
208 |
|
|
*/ |
209 |
|
|
typedef struct Srv { |
210 |
|
|
disp *snd; /* method implementation */ |
211 |
|
|
file *con; /* connection */ |
212 |
|
|
} Srv; |
213 |
|
|
/** |
214 |
|
|
interface a stream |
215 |
|
|
*/ |
216 |
|
|
extern int OPT_STDCALL oSrv ( Srv *self, Msg msg ); |
217 |
|
|
|
218 |
|
|
|
219 |
|
|
/* |
220 |
|
|
database object |
221 |
|
|
NOTE that these are childs of session, so all status is per session. |
222 |
|
|
*/ |
223 |
|
|
typedef struct Dbo { |
224 |
|
|
disp *snd; |
225 |
|
|
HTable *reg; /* views etc */ |
226 |
|
|
factory *fac; /* child factory */ |
227 |
|
|
Db *db; /* shared by the Dbos */ |
228 |
|
|
Qry *qry; /* chain of queries */ |
229 |
|
|
unsigned qid; /* number of last query, 0 = none */ |
230 |
|
|
unsigned rid; /* number of last written rec, 0 = none */ |
231 |
|
|
/* options */ |
232 |
|
|
unsigned p; /* position limit for snapshot read, 0 = none */ |
233 |
|
|
} Dbo; |
234 |
|
|
/** |
235 |
|
|
handle db access |
236 |
|
|
*/ |
237 |
|
|
extern int OPT_STDCALL oDbo ( Dbo *self, Msg msg ); |
238 |
|
|
|
239 |
|
|
extern Dbo *newDbo ( char *name ); /* constructor */ |
240 |
|
|
extern void delDbo ( Dbo *self ); /* destructor */ |
241 |
|
|
|
242 |
|
|
|
243 |
|
|
/* ****************************************************************** */ |
244 |
|
|
/* */ |
245 |
|
|
/* HANDLERS FOR VARIOUS STANDARD MESSAGES */ |
246 |
|
|
/* */ |
247 |
|
|
/* ****************************************************************** */ |
248 |
|
|
|
249 |
|
|
|
250 |
|
|
/* |
251 |
|
|
Process a pipe message '|'. |
252 |
|
|
The leader is parsed for the subfields '|'. Each of which should contain a |
253 |
|
|
valid messagename, options may be given in following subfields terminated by |
254 |
|
|
the next '|' subfield or the end of the leader. The output of the first |
255 |
|
|
method is used as data input for the next and so on. The first submessage |
256 |
|
|
may start directly after the primary field w/o the '|' identifier. |
257 |
|
|
*/ |
258 |
|
|
extern int OPT_STDCALL mPipe ( Obj *self, Msg msg ); |
259 |
|
|
|
260 |
|
|
/* |
261 |
|
|
Process a compound message ';'. |
262 |
|
|
The leader is parsed for the subfields ';'. Each of which should contain a |
263 |
|
|
valid messagename, options may be given in following subfields terminated by |
264 |
|
|
the next ';' subfield or the end of the leader. Each message is processed |
265 |
|
|
separately, given data is used for all messages. The first submessage may |
266 |
|
|
start directly after the primary field w/o the ';' identifier. |
267 |
|
|
*/ |
268 |
|
|
extern int OPT_STDCALL mComp ( Obj *self, Msg msg ); |
269 |
|
|
|
270 |
|
|
/* |
271 |
|
|
Process a comment message '#'. |
272 |
|
|
*/ |
273 |
|
|
extern int OPT_STDCALL mComm ( Obj *self, Msg msg ); |
274 |
|
|
|
275 |
|
|
|
276 |
|
|
#define PW_H |
277 |
|
|
#endif /* PW_H */ |