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: lstb.c,v 1.41 2003/06/15 15:57:43 mawag Exp $ |
25 |
implementation of client side session and communication functions. |
26 |
*/ |
27 |
|
28 |
#include <errno.h> |
29 |
#include <limits.h> /* PATH_MAX */ |
30 |
#include <stdarg.h> |
31 |
#include <stdio.h> |
32 |
#include <string.h> |
33 |
|
34 |
#include "openisis.h" |
35 |
#include "loi.h" |
36 |
#include "lcli.h" |
37 |
#include "ldb.h" |
38 |
#include "ldsp.h" |
39 |
#include "lfdt.h" |
40 |
#include "luti.h" |
41 |
|
42 |
#ifdef WIN32 |
43 |
#define snprintf _snprintf |
44 |
#define vsnprintf _vsnprintf |
45 |
#endif |
46 |
|
47 |
#define LSTB_STHOSTLEN 32 |
48 |
|
49 |
#define LSTB_MAXDBS 255 /* according to OPENISIS_DBIDMSK */ |
50 |
#define LSTB_MAXSTUBS 255 /* according to OPENISIS_SCIDMSK */ |
51 |
|
52 |
#define LSTB_INCRDB 8 |
53 |
#define LSTB_INCRSTUB 8 |
54 |
|
55 |
/* ************************************************************ |
56 |
* meta |
57 |
*/ |
58 |
|
59 |
/* stub id 0 has idx -1 */ |
60 |
/* stub id 0x0100 has idx 0 */ |
61 |
|
62 |
#define SC_X2I(s) ( ( (1 + (s)) << 8 ) & OPENISIS_SCIDMSK ) |
63 |
|
64 |
#define SC_I2X(s) ( ( ((s) & OPENISIS_SCIDMSK) >> 8 ) - 1 ) |
65 |
|
66 |
#define DB_X2I(d,s) ( ((s) & OPENISIS_SCIDMSK) | ((d) & OPENISIS_DBIDMSK) ) |
67 |
|
68 |
#define DB_I2X(d) ( (d) & OPENISIS_DBIDMSK ) |
69 |
|
70 |
#define DB_IDX_OK(st,idx) \ |
71 |
(0 <= (idx) && (st)->head.ndbs > (idx) && * (st)->head.dbs[idx]->name) |
72 |
|
73 |
/* ************************************************************ |
74 |
* client view of db |
75 |
*/ |
76 |
|
77 |
typedef struct { |
78 |
Db head; |
79 |
} CDb; |
80 |
|
81 |
static void cdbCtor (CDb *that, |
82 |
const char *name, int dbid, int tms, Fdt *fdt, Rec *cfg |
83 |
) { |
84 |
strncpy (that->head.name, name, DBNLEN - 1) [DBNLEN - 1] = 0; |
85 |
that->head.dbid = dbid; |
86 |
that->head.tms = tms; |
87 |
that->head.fdt = fdt; |
88 |
that->head.cfg = cfg; |
89 |
} |
90 |
|
91 |
static void cdbDtor (CDb *that) { |
92 |
if (that->head.fdt) { |
93 |
fFree (that->head.fdt); |
94 |
} |
95 |
if (that->head.cfg) { |
96 |
mFree (that->head.cfg); |
97 |
} |
98 |
memset (that, 0, sizeof (CDb)); |
99 |
} |
100 |
|
101 |
/* ************************************************************ |
102 |
* client session |
103 |
*/ |
104 |
|
105 |
typedef struct OpenIsisStb { |
106 |
Schema head; |
107 |
char host[LSTB_STHOSTLEN]; |
108 |
int port; |
109 |
int srq; /* rqs serial no */ |
110 |
Rec *rqs; /* last request */ |
111 |
Rec *rsp; /* last response */ |
112 |
Db *rdb; /* db of embedded rsp recs */ |
113 |
CDb *dbase; /* db array of non-local schema */ |
114 |
LutiLT hsh; |
115 |
CliChnl chn; |
116 |
OpenIsisStbRqsProc *rqsp; |
117 |
OpenIsisStbDelProc *delp; |
118 |
void *cld; /* client_data of rqsp */ |
119 |
/*MMM deprecated*/ |
120 |
OpenIsisRspCb *actcb; |
121 |
void *actcld; |
122 |
OpenIsisStubCbData cbdta; |
123 |
} OpenIsisStb; |
124 |
|
125 |
Stub stub0 = 0; |
126 |
|
127 |
static Stub RmtStubs = 0; |
128 |
static int NumStubs = 0; |
129 |
|
130 |
static LutiLT StubLT = 0; |
131 |
|
132 |
#define STBSIZE (sizeof(Stb)) |
133 |
|
134 |
static int stbLocalRqs (Stub that, Rec *rqs); |
135 |
static int stbSyncRqs (Stub that, Rec *rqs); |
136 |
|
137 |
static void stbClear (Stub that) { |
138 |
memset (that, 0, STBSIZE); |
139 |
that->chn.sd = -1; |
140 |
} |
141 |
|
142 |
static int stbCtor (Stub that, |
143 |
const char *name, int scid, Rec *cfg, |
144 |
OpenIsisStbRqsProc *rqsp, OpenIsisStbDelProc *delp, void *cld, |
145 |
OpenIsisStubCbData *cbd |
146 |
) { |
147 |
strncpy (that->head.name, name, SCNLEN - 1) [SCNLEN - 1] = 0; |
148 |
that->head.scid = scid; |
149 |
if (scid) { |
150 |
if (! rString (cfg, OPENISIS_SC_HOST, 0, that->host, LSTB_STHOSTLEN)) { |
151 |
return 0; |
152 |
} |
153 |
that->port = rInt (cfg, OPENISIS_SC_PORT, 0, 0); |
154 |
if (0 >= that->port) { |
155 |
return 0; |
156 |
} |
157 |
if (rqsp) { |
158 |
that->rqsp = rqsp; |
159 |
} |
160 |
else { |
161 |
that->rqsp = &stbSyncRqs; |
162 |
} |
163 |
} |
164 |
else { |
165 |
that->rqsp = &stbLocalRqs; |
166 |
} |
167 |
that->head.cfg = |
168 |
rSet (cfg, RCHG | RDIS, OPENISIS_SC_NAME, that->head.name, 0); |
169 |
that->delp = delp; |
170 |
that->cld = cld; |
171 |
that->hsh = luti_ltnew (); |
172 |
if (cbd) { |
173 |
memcpy (&that->cbdta, cbd, sizeof (OpenIsisStubCbData)); |
174 |
} |
175 |
luti_ltadd (StubLT, that->head.name, scid); |
176 |
return !0; |
177 |
} |
178 |
|
179 |
/* return idx or -err */ |
180 |
static int cdbNewIdx (Stub that) { |
181 |
int ndb = that->head.ndbs; |
182 |
int rt, j; |
183 |
for (j = 0; ndb > j; ++j) { |
184 |
if (! * that->dbase[j].head.name) { |
185 |
return j; |
186 |
} |
187 |
} |
188 |
rt = luti_ptrincr (&that->dbase, &ndb, |
189 |
LSTB_INCRDB, sizeof (CDb), LSTB_MAXDBS); |
190 |
if (0 > rt) { |
191 |
return sMsg (ERR_NOMEM, "%s: cdbNewIdx: out of memory", |
192 |
that->head.name); |
193 |
} |
194 |
rt = luti_ptrincr (&that->head.dbs, &that->head.ndbs, |
195 |
LSTB_INCRDB, sizeof (CDb*), LSTB_MAXDBS); |
196 |
if (0 > rt) { |
197 |
return sMsg (ERR_NOMEM, "%s: cdbNewIdx: out of memory", |
198 |
that->head.name); |
199 |
} |
200 |
for (j = that->head.ndbs; 0 <= --j; ) { |
201 |
that->head.dbs[j] = (Db*) (that->dbase + j); |
202 |
} |
203 |
return rt; |
204 |
} |
205 |
|
206 |
/* return bool newly allocated or -err */ |
207 |
static int cdbNewIdx0 (Stub that, int dbid) { |
208 |
int rt; |
209 |
if (dbid < that->head.ndbs) { |
210 |
if (that->head.dbs[dbid]) { |
211 |
return 0; |
212 |
} |
213 |
return 1; |
214 |
} |
215 |
rt = luti_ptrincr (&that->head.dbs, &that->head.ndbs, |
216 |
1 + dbid - that->head.ndbs, sizeof (CDb*), -1); |
217 |
if (0 > rt) { |
218 |
return sMsg (ERR_NOMEM, "%s: cdbNewIdx0(%d): out of memory", |
219 |
that->head.name, dbid); |
220 |
} |
221 |
return 1; |
222 |
} |
223 |
|
224 |
static int stbNewIdx () { |
225 |
int j; |
226 |
for (j = 0; NumStubs > j; ++j) { |
227 |
if (! * RmtStubs[j].head.name) { |
228 |
return j; |
229 |
} |
230 |
} |
231 |
j = luti_ptrincr (&RmtStubs, &NumStubs, |
232 |
LSTB_INCRSTUB, STBSIZE, LSTB_MAXSTUBS); |
233 |
/* stbClear (RmtStubs + j) done in nOpen */ |
234 |
return j; |
235 |
} |
236 |
|
237 |
static Stub stbById (int sid) { |
238 |
int idx; |
239 |
if (0 > sid || ! stub0) { |
240 |
return 0; |
241 |
} |
242 |
if (0 == sid) { |
243 |
return stub0; |
244 |
} |
245 |
idx = SC_I2X (sid); |
246 |
if (0 > idx) { |
247 |
log_msg (LOG_ERROR, "stbById: illegal id %x", sid); |
248 |
return 0; |
249 |
} |
250 |
if (NumStubs <= idx) { |
251 |
return 0; |
252 |
} |
253 |
if (! * RmtStubs[idx].head.name) { |
254 |
return 0; |
255 |
} |
256 |
return RmtStubs + idx; |
257 |
} |
258 |
|
259 |
static void stbDtor (Stub that) { |
260 |
luti_ltrmv (StubLT, that->head.name); |
261 |
if (that->cbdta.delcb) { |
262 |
if (that->actcld) { |
263 |
(*that->cbdta.delcb) ( |
264 |
that->cbdta.delcld, that, that->actcld); |
265 |
} |
266 |
if (that->cbdta.dfltcld) { |
267 |
(*that->cbdta.delcb) ( |
268 |
that->cbdta.delcld, that, that->cbdta.dfltcld); |
269 |
} |
270 |
(*that->cbdta.delcb) (that->cbdta.delcld, that, 0); |
271 |
} |
272 |
if (that->dbase) { |
273 |
int j; |
274 |
for (j = that->head.ndbs; 0 <= --j; ) { |
275 |
if (* that->dbase[j].head.name) { |
276 |
cdbDtor (that->dbase + j); |
277 |
} |
278 |
} |
279 |
mFree (that->dbase); |
280 |
} |
281 |
if (that->head.dbs) { |
282 |
mFree (that->head.dbs); |
283 |
} |
284 |
if (that->head.cfg) { |
285 |
mFree (that->head.cfg); |
286 |
} |
287 |
luti_ltdel (that->hsh); |
288 |
nClean (that); |
289 |
stbClear (that); |
290 |
} |
291 |
|
292 |
static int stbDbidFromName (Stub that, const char *dbn) { |
293 |
int id; |
294 |
if (! dbn) { |
295 |
return -1; |
296 |
} |
297 |
id = luti_ltget (that->hsh, dbn); |
298 |
return id; |
299 |
} |
300 |
|
301 |
static int stbDbIdxFromName (Stub that, const char *dbn) { |
302 |
int idx = stbDbidFromName (that, dbn); |
303 |
if (0 > idx) { |
304 |
return -1; |
305 |
} |
306 |
idx = DB_I2X (idx); |
307 |
if (! DB_IDX_OK (that, idx)) { |
308 |
return -1; |
309 |
} |
310 |
return idx; |
311 |
} |
312 |
|
313 |
static int stbOpenDb (Stub that) { |
314 |
char dbn[DBNLEN]; |
315 |
Fdt *fdt; |
316 |
Rec *cfg; |
317 |
int idx, dbid, tms; |
318 |
int newdb = 0; |
319 |
|
320 |
if (! rString (that->rsp, OPENISIS_COM_DBN, 0, dbn, DBNLEN)) { |
321 |
return sMsg (ERR_IDIOT, "%s: stbOpenDb: missing db name in rsp", |
322 |
that->head.name); |
323 |
} |
324 |
idx = stbDbIdxFromName (that, dbn); |
325 |
|
326 |
if (0 > idx) { |
327 |
idx = cdbNewIdx (that); |
328 |
if (0 > idx) { |
329 |
return idx; |
330 |
} |
331 |
newdb = !0; |
332 |
} |
333 |
else { |
334 |
cdbDtor (that->dbase + idx); |
335 |
} |
336 |
|
337 |
fdt = fRec2Fdt (that->rsp); |
338 |
cfg = luti_unwrap (that->rsp, 0, OPENISIS_COM_CFG, -1); |
339 |
tms = rInt (that->rsp, OPENISIS_COM_TMS, 0, 0); |
340 |
dbid = DB_X2I (idx, that->head.scid); |
341 |
|
342 |
cdbCtor (that->dbase + idx, dbn, dbid, tms, fdt, cfg); |
343 |
|
344 |
if (newdb) { |
345 |
luti_ltadd (that->hsh, dbn, dbid); |
346 |
} |
347 |
return 0; |
348 |
} |
349 |
|
350 |
static int stbOpenDb0 (Stub that) { |
351 |
Db *dbh; |
352 |
int newdb = 0; |
353 |
int dbid = rInt (that->rsp, OPENISIS_RSP_DBID, -1, 0); |
354 |
if (0 > dbid) { |
355 |
return sMsg (ERR_IDIOT, "stbOpenDb0: missing dbid in rsp"); |
356 |
} |
357 |
|
358 |
newdb = cdbNewIdx0 (that, dbid); |
359 |
if (0 > newdb) { |
360 |
return newdb; |
361 |
} |
362 |
|
363 |
dbh = ldb_getdb (dbid); |
364 |
if (! dbh) { |
365 |
return sMsg (ERR_TRASH, "stbOpenDb0: no such db %d", dbid); |
366 |
} |
367 |
log_msg (LOG_INFO, "stbOpenDb0 %d %s", dbid, dbh->name); |
368 |
|
369 |
that->head.dbs[dbid] = dbh; |
370 |
if (newdb) { |
371 |
luti_ltadd (that->hsh, dbh->name, dbid); |
372 |
} |
373 |
return 0; |
374 |
} |
375 |
|
376 |
static int stbCloseDb (Stub that) { |
377 |
char dbn[DBNLEN]; |
378 |
CDb *db; |
379 |
int dbid; |
380 |
if (! rString (that->rsp, OPENISIS_COM_DBN, 0, dbn, sizeof (dbn))) { |
381 |
return sMsg (ERR_IDIOT, "%s: stbCloseDb: missing db name in rsp", |
382 |
that->head.name); |
383 |
} |
384 |
dbid = stbDbIdxFromName (that, dbn); |
385 |
if (0 > dbid) { |
386 |
return sMsg (ERR_TRASH, "%s: stbCloseDb: illegal db name <%s> in rsp", |
387 |
that->head.name, dbn); |
388 |
} |
389 |
db = that->dbase + dbid; |
390 |
luti_ltrmv (that->hsh, db->head.name); |
391 |
cdbDtor (db); |
392 |
return 0; |
393 |
} |
394 |
|
395 |
static int stbCloseDb0 (Stub that) { |
396 |
char dbn[DBNLEN]; |
397 |
int dbid = rInt (that->rsp, OPENISIS_RSP_DBID, -1, 0); |
398 |
if (0 > dbid) { |
399 |
return sMsg (ERR_IDIOT, "stbCloseDb0: missing dbid in rsp"); |
400 |
} |
401 |
if (that->head.ndbs <= dbid) { |
402 |
return sMsg (ERR_TRASH, "stbCloseDb0: illegal dbid %d(%d) in rsp", |
403 |
dbid, that->head.ndbs); |
404 |
} |
405 |
if (! rString (that->rsp, OPENISIS_COM_DBN, 0, dbn, DBNLEN)) { |
406 |
return sMsg (ERR_IDIOT, "stbCloseDb0: missing db name in rsp\n"); |
407 |
} |
408 |
log_msg (LOG_INFO, "stbCloseDb0 %d %s", dbid, dbn); |
409 |
luti_ltrmv (that->hsh, dbn); |
410 |
that->head.dbs[dbid] = 0; |
411 |
return 0; |
412 |
} |
413 |
|
414 |
/* (local) response callback |
415 |
*/ |
416 |
static int stbRspCb (Rec **rsp, void *cld) { |
417 |
Stub that; |
418 |
Rec *rsp2; |
419 |
int sid, ser, err, err2, err3; |
420 |
|
421 |
(void)cld; |
422 |
sid = rInt (*rsp, OPENISIS_COM_SID, -1, 0); |
423 |
ser = rInt (*rsp, OPENISIS_COM_SER, -1, 0); |
424 |
err = rInt (*rsp, OPENISIS_RSP_ERR, -1, 0); |
425 |
|
426 |
that = stbById (sid); |
427 |
if (! that) { |
428 |
return sMsg (ERR_TRASH, "illegal stub id %d in stbRspCb\n", sid); |
429 |
} |
430 |
if (ser != that->srq) { |
431 |
return sMsg (ERR_TRASH, "%s: rqs serial mismatch %d != %d", |
432 |
that->head.name, ser, that->srq); |
433 |
} |
434 |
if (! that->rqs) { |
435 |
return sMsg (ERR_TRASH, "%s/%d: response without request", |
436 |
that->head.name, sid); |
437 |
} |
438 |
if (that->rsp) { |
439 |
sMsg (ERR_TRASH, "%s: multiple responses", |
440 |
that->head.name); |
441 |
mFree (that->rsp); |
442 |
} |
443 |
that->rdb = 0; |
444 |
that->rsp = *rsp; |
445 |
*rsp = 0; |
446 |
|
447 |
err2 = err3 = 0; |
448 |
|
449 |
if (0 == err) { |
450 |
int rtyp = rInt (that->rqs, OPENISIS_RQS_TYPE, -1, 0); |
451 |
switch (rtyp) { |
452 |
|
453 |
case OPENISIS_RQST_LSDB: |
454 |
case OPENISIS_RQST_EVAL: |
455 |
break; |
456 |
|
457 |
case OPENISIS_RQST_CLOS: |
458 |
if (sid) { |
459 |
err2 = sMsg (ERR_IDIOT, "%s: db close on remote stub", |
460 |
that->head.name); |
461 |
} |
462 |
else { |
463 |
err2 = stbCloseDb0 (that); |
464 |
} |
465 |
break; |
466 |
|
467 |
case OPENISIS_RQST_OPEN: |
468 |
if (sid) { |
469 |
err2 = sMsg (ERR_IDIOT, "%s: db open on remote stub", |
470 |
that->head.name); |
471 |
break; |
472 |
} |
473 |
err2 = stbOpenDb0 (that); |
474 |
goto setdb; |
475 |
|
476 |
case OPENISIS_RQST_MNT: |
477 |
if (0 == sid) { |
478 |
err2 = sMsg (ERR_IDIOT, "db mount on local stub"); |
479 |
break; |
480 |
} |
481 |
err2 = stbOpenDb (that); |
482 |
goto setdb; |
483 |
|
484 |
default: |
485 |
setdb: { |
486 |
char dbn[DBNLEN]; |
487 |
int rdid, rx; |
488 |
if (! rString (that->rsp, OPENISIS_COM_DBN, 0, dbn, sizeof(dbn))) { |
489 |
if (sid) { |
490 |
err2 = sMsg (ERR_IDIOT, |
491 |
"%s: stbRspCb: missing db name in rsp", |
492 |
that->head.name); |
493 |
} |
494 |
else { |
495 |
err2 = sMsg (ERR_IDIOT, |
496 |
"stbRspCb: missing db name in rsp"); |
497 |
} |
498 |
} |
499 |
else { |
500 |
rdid = stbDbidFromName (that, dbn); |
501 |
if (0 > rdid) { |
502 |
if (sid) { |
503 |
err2 = sMsg (ERR_TRASH, |
504 |
"%s: stbRspCb: illegal db name <%s> in rsp", |
505 |
that->head.name, dbn); |
506 |
} |
507 |
else { |
508 |
err2 = sMsg (ERR_TRASH, |
509 |
"stbRspCb: illegal db name <%s> in rsp", dbn); |
510 |
} |
511 |
} |
512 |
else { |
513 |
/* see nDbById */ |
514 |
rx = DB_I2X (rdid); |
515 |
if (! DB_IDX_OK (that, rx)) { |
516 |
if (sid) { |
517 |
err2 = sMsg (ERR_TRASH, |
518 |
"%s: stbRspCb: illegal db id %d %d <%s>", |
519 |
that->head.name, rdid, rx, dbn); |
520 |
} |
521 |
else { |
522 |
err2 = sMsg (ERR_TRASH, |
523 |
"stbRspCb: illegal db id %d %d <%s>", |
524 |
rdid, rx, dbn); |
525 |
} |
526 |
} |
527 |
else { |
528 |
that->rdb = that->head.dbs[rx]; |
529 |
} |
530 |
} |
531 |
} |
532 |
} |
533 |
} /* switch */ |
534 |
} |
535 |
else { /* err */ |
536 |
int tms; |
537 |
tms = rInt (that->rsp, OPENISIS_COM_TMS, 0, 0); |
538 |
if (tms && sid) { /* remounted */ |
539 |
err2 = stbCloseDb (that); |
540 |
} |
541 |
} |
542 |
|
543 |
rsp2 = rAddI (that->rsp, OPENISIS_RSP_CERR, err2, !0); |
544 |
if (rsp2) { |
545 |
that->rsp = rsp2; |
546 |
} |
547 |
|
548 |
if (that->actcb) { |
549 |
err3 = (*that->actcb) (that->actcld, |
550 |
that, that->rsp, that->rdb); |
551 |
if (that->actcld && that->cbdta.delcb) { |
552 |
(*that->cbdta.delcb) ( |
553 |
that->cbdta.delcld, that, that->actcld); |
554 |
} |
555 |
that->actcb = 0; |
556 |
that->actcld = 0; |
557 |
} |
558 |
else if (that->cbdta.dfltcb) { |
559 |
err3 = (*that->cbdta.dfltcb) (that->cbdta.dfltcld, |
560 |
that, that->rsp, that->rdb); |
561 |
} |
562 |
|
563 |
sMsg (LOG_VERBOSE, "stbRspCb(%s): %d/%d err = %x,%x,%x", |
564 |
that->head.name, sid, ser, err, err2, err3); |
565 |
|
566 |
return err3; |
567 |
} |
568 |
|
569 |
static int stbLocalRqs (Stub that, Rec *rqs) { |
570 |
(void)that; |
571 |
return ldspProcess (rqs, 0, &stbRspCb, 0); |
572 |
} |
573 |
|
574 |
static int stbSyncRqs (Stub that, Rec *rqs) { |
575 |
Rec *rsp; |
576 |
int rt; |
577 |
if (0 > that->chn.sd) { |
578 |
rt = cliConnect (&that->chn, that->host, that->port); |
579 |
if (0 > rt) { |
580 |
return rt; |
581 |
} |
582 |
} |
583 |
rt = cliWrite (&that->chn, rqs); |
584 |
if (0 > rt) { |
585 |
return rt; |
586 |
} |
587 |
rsp = cliRead (&that->chn); |
588 |
if (! rsp) { |
589 |
return sMsg (ERR_IO, "stbSyncRqs: read error %d - %s", |
590 |
that->chn.err, strerror (that->chn.err)); |
591 |
} |
592 |
rt = stbRspCb (&rsp, 0); |
593 |
if (rsp) { |
594 |
mFree (rsp); |
595 |
} |
596 |
return rt; |
597 |
} |
598 |
|
599 |
/* ************************************************************ |
600 |
package functions |
601 |
*/ |
602 |
|
603 |
/* ************************************************************ |
604 |
public functions |
605 |
*/ |
606 |
|
607 |
Stub nInit ( |
608 |
int argc, const char **argv, OpenIsisStubCbData *dta |
609 |
) { |
610 |
Rec *cfg = 0; |
611 |
|
612 |
if (stub0) { |
613 |
return stub0; |
614 |
} |
615 |
|
616 |
StubLT = luti_ltnew (); |
617 |
stub0 = mAlloc (STBSIZE); |
618 |
stbClear (stub0); |
619 |
|
620 |
if (0 < argc) { |
621 |
char buf[PATH_MAX]; |
622 |
char *logn; |
623 |
int logl; |
624 |
|
625 |
cfg = rSet (0, RFDT | RARGV | RIGN | argc, openIsisFdtSyspar, argv); |
626 |
|
627 |
logn = rString (cfg, OPENISIS_SLOGF, 0, buf, sizeof(buf)); |
628 |
logl = rInt (cfg, OPENISIS_SLOGV, -1, 0); |
629 |
if (logn || 0 <= logl) { |
630 |
cLog (logl, logn); |
631 |
} |
632 |
} |
633 |
|
634 |
stbCtor (stub0, "", 0, cfg, 0, 0, 0, dta); |
635 |
return stub0; |
636 |
} |
637 |
|
638 |
Stub nOpen ( |
639 |
const char *name, int argc, const char *argv[], OpenIsisStubCbData *dta |
640 |
) { |
641 |
OpenIsisStb buf; |
642 |
Stub that; |
643 |
Rec *cfg = 0; |
644 |
int idx, sid; |
645 |
|
646 |
if (! stub0 || ! name || ! *name) { |
647 |
return 0; |
648 |
} |
649 |
|
650 |
idx = luti_ltget (StubLT, name); |
651 |
if (0 <= idx) { |
652 |
idx = SC_I2X (idx); |
653 |
if (0 > idx || NumStubs <= idx || ! * RmtStubs[idx].head.name) { |
654 |
log_msg (LOG_ERROR, "nOpen: illegal idx %d(%d) for %s", |
655 |
idx, NumStubs, name); |
656 |
return 0; |
657 |
} |
658 |
return RmtStubs + idx; |
659 |
} |
660 |
|
661 |
idx = stbNewIdx (); |
662 |
if (0 > idx) { |
663 |
return 0; |
664 |
} |
665 |
if (0 < argc) { |
666 |
cfg = rSet (0, RFDT | RARGV | RIGN | argc, openIsisFdtScheme, argv); |
667 |
} |
668 |
sid = SC_X2I (idx); |
669 |
stbClear (&buf); |
670 |
if (! stbCtor (&buf, name, sid, cfg, 0, 0, 0, dta)) { |
671 |
if (cfg) { |
672 |
mFree (cfg); |
673 |
} |
674 |
return 0; |
675 |
} |
676 |
|
677 |
that = RmtStubs + idx; |
678 |
memcpy (that, &buf, STBSIZE); |
679 |
return that; |
680 |
} |
681 |
|
682 |
void nClose (Stub that) { |
683 |
if (that && *that->head.name) { |
684 |
stbDtor (that); |
685 |
} |
686 |
} |
687 |
|
688 |
void nDeinit () { |
689 |
if (stub0) { |
690 |
int j; |
691 |
if (RmtStubs) { |
692 |
for (j = NumStubs; 0 <= --j; ) { |
693 |
if (* RmtStubs[j].head.name) { |
694 |
stbDtor (RmtStubs + j); |
695 |
} |
696 |
} |
697 |
mFree (RmtStubs); |
698 |
RmtStubs = 0; |
699 |
NumStubs = 0; |
700 |
} |
701 |
for (j = stub0->head.ndbs; 0 <= --j; ) { |
702 |
if (stub0->head.dbs[j]) { |
703 |
cDClose (stub0->head.dbs[j]->dbid); |
704 |
} |
705 |
} |
706 |
stbDtor (stub0); |
707 |
mFree (stub0); |
708 |
stub0 = 0; |
709 |
luti_ltdel (StubLT); |
710 |
StubLT = 0; |
711 |
} |
712 |
} |
713 |
|
714 |
Schema* nSchema (Stub that) { |
715 |
int idx; |
716 |
if (that && ( stub0 == that || ( *that->head.name && |
717 |
0 <= (idx = SC_I2X (that->head.scid)) && NumStubs > idx |
718 |
))) { |
719 |
return &that->head; |
720 |
} |
721 |
return 0; |
722 |
} |
723 |
|
724 |
void nClean (Stub that) { |
725 |
if (that->rqs) { |
726 |
mFree (that->rqs); |
727 |
that->rqs = 0; |
728 |
} |
729 |
if (that->rsp) { |
730 |
mFree (that->rsp); |
731 |
that->rsp = 0; |
732 |
} |
733 |
that->rdb = 0; |
734 |
} |
735 |
|
736 |
int nSend (Stub that, |
737 |
Rec *rqs, OpenIsisRspCb *actcb, void *actcld, int dup |
738 |
) { |
739 |
char buf[DBNLEN]; |
740 |
char sid[16]; |
741 |
char ser[16]; |
742 |
char tms[16]; |
743 |
char *dbl, *dbn; |
744 |
int dbid, rtyp, setn; |
745 |
|
746 |
if (!(that && rqs)) { |
747 |
return sMsg (ERR_IDIOT, "nSend: null pointer %x %x", |
748 |
(int)that, (int)rqs); |
749 |
} |
750 |
if (stub0 != that && ! *that->head.name) { |
751 |
return sMsg (ERR_IDIOT, "nSend: invalid stub"); |
752 |
} |
753 |
setn = !0; |
754 |
rtyp = rInt (rqs, OPENISIS_RQS_TYPE, -1, 0); |
755 |
switch (rtyp) { |
756 |
case -1: |
757 |
return sMsg (ERR_IDIOT, "nSend(%s): request without type", |
758 |
that->head.name); |
759 |
case OPENISIS_RQST_LSDB: |
760 |
case OPENISIS_RQST_EVAL: |
761 |
setn = 0; |
762 |
break; |
763 |
case OPENISIS_RQST_OPEN: |
764 |
case OPENISIS_RQST_CLOS: |
765 |
if (stub0 != that) { |
766 |
return sMsg (ERR_IDIOT, "nSend(%s): request %d denied", |
767 |
that->head.name, rtyp); |
768 |
} |
769 |
break; |
770 |
case OPENISIS_RQST_MNT: |
771 |
if (stub0 == that) { |
772 |
return sMsg (ERR_IDIOT, "nSend: local mount denied"); |
773 |
} |
774 |
rqs = rSet (rqs, RFDT | RDIS | RCHG, openIsisFdtRqs, |
775 |
OPENISIS_COM_TMS, "0", 0); |
776 |
if (! rqs) { |
777 |
return sMsg (ERR_NOMEM, "nSend(%s): out of memory", |
778 |
that->head.name); |
779 |
} |
780 |
break; |
781 |
} |
782 |
|
783 |
dbid = -1; |
784 |
dbn = 0; |
785 |
dbl = that->rdb ? that->rdb->name : 0; |
786 |
nClean (that); |
787 |
|
788 |
i2a (sid, that->head.scid); |
789 |
if (0 >= ++that->srq) { |
790 |
that->srq = 1; |
791 |
log_msg (LOG_INFO, "stub %s: srq loop over 0", that->head.name); |
792 |
} |
793 |
i2a (ser, that->srq); |
794 |
|
795 |
if (setn) { |
796 |
if ((dbn = rString (rqs, OPENISIS_COM_DBN, 0, buf, DBNLEN))) { |
797 |
setn = 0; |
798 |
} |
799 |
else { |
800 |
if (dbl) { |
801 |
dbn = dbl; |
802 |
} |
803 |
else { |
804 |
dbn = rString (that->head.cfg, |
805 |
OPENISIS_SC_DFLTDB, 0, buf, DBNLEN); |
806 |
} |
807 |
} |
808 |
if (! dbn) { |
809 |
return sMsg (ERR_IDIOT, "nSend(%s): request without db name", |
810 |
that->head.name); |
811 |
} |
812 |
if (0 > rInt (rqs, OPENISIS_COM_TMS, -1, 0)) { |
813 |
dbid = stbDbIdxFromName (that, dbn); |
814 |
if (0 <= dbid) { |
815 |
i2a (tms, that->head.dbs[dbid]->tms); |
816 |
} |
817 |
} |
818 |
} |
819 |
|
820 |
if (dup) { |
821 |
rqs = rDup (rqs, 0, 0); |
822 |
if (! rqs) { |
823 |
return -1; |
824 |
} |
825 |
} |
826 |
|
827 |
rqs = rSet (rqs, RFDT | RDIS | RCHG, openIsisFdtRqs, |
828 |
OPENISIS_COM_SID, sid, OPENISIS_COM_SER, ser, |
829 |
0 <= dbid ? OPENISIS_COM_TMS : 0, tms, 0); |
830 |
if (! rqs) { |
831 |
return sMsg (ERR_NOMEM, "nSend(%s): out of memory", |
832 |
that->head.name); |
833 |
} |
834 |
if (setn) { |
835 |
rqs = rSet (rqs, RFDT | RDIS | RCHG, openIsisFdtRqs, |
836 |
OPENISIS_COM_DBN, dbn, 0); |
837 |
if (! rqs) { |
838 |
return sMsg (ERR_NOMEM, "nSend(%s): out of memory", |
839 |
that->head.name); |
840 |
} |
841 |
} |
842 |
|
843 |
that->rqs = rqs; |
844 |
|
845 |
if (that->actcld && that->cbdta.delcb) { |
846 |
/* ooups */ |
847 |
(*that->cbdta.delcb) ( |
848 |
that->cbdta.delcld, that, that->actcld); |
849 |
} |
850 |
if (actcb) { |
851 |
that->actcb = actcb; |
852 |
that->actcld = actcld; |
853 |
} |
854 |
else { |
855 |
that->actcb = 0; |
856 |
that->actcld = 0; |
857 |
} |
858 |
|
859 |
return (*that->rqsp) (that, that->rqs); |
860 |
} |
861 |
|
862 |
Rec* nRecv (Stub that, Db **db) { |
863 |
if (that && ( |
864 |
stub0 == that || *that->head.name |
865 |
)) { |
866 |
if (db) { |
867 |
*db = that->rdb; |
868 |
} |
869 |
return that->rsp; |
870 |
} |
871 |
return 0; |
872 |
} |
873 |
|
874 |
Db* nDbByName (Stub that, const char *dbname) { |
875 |
if (that && ( |
876 |
stub0 == that || *that->head.name |
877 |
)) { |
878 |
int dbid = stbDbIdxFromName (that, dbname); |
879 |
if (0 <= dbid) { |
880 |
return that->head.dbs[dbid]; |
881 |
} |
882 |
} |
883 |
return 0; |
884 |
} |
885 |
|
886 |
Db* nDbById (int id) { |
887 |
Stub that = stbById (id & OPENISIS_SCIDMSK); |
888 |
if (! that) { |
889 |
return 0; |
890 |
} |
891 |
id = DB_I2X (id); |
892 |
if (! DB_IDX_OK (that, id)) { |
893 |
return 0; |
894 |
} |
895 |
return that->head.dbs[id]; |
896 |
} |
897 |
|
898 |
#define FREEPTR(p) if (p) { mFree (p); p = 0; } |
899 |
#define FREEROW if (rowids) { FREEPTR(*rowids) } |
900 |
|
901 |
int nResult ( |
902 |
Stub that, int **rowids, Rec ***recs, Db **db, int *tot |
903 |
) { |
904 |
Field *F; |
905 |
Rec **R; |
906 |
int *I; |
907 |
int numt, numr, err, pos, j; |
908 |
|
909 |
if (rowids) { |
910 |
*rowids = 0; |
911 |
} |
912 |
if (recs) { |
913 |
*recs = 0; |
914 |
} |
915 |
if (db) { |
916 |
*db = 0; |
917 |
} |
918 |
if (tot) { |
919 |
*tot = 0; |
920 |
} |
921 |
if (! that) { |
922 |
return sMsg (ERR_IDIOT, "nGetResult: null pointer"); |
923 |
} |
924 |
if (! that->rsp) { |
925 |
return sMsg (ERR_IDIOT, "nGetResult(%s): no response", |
926 |
that->head.name); |
927 |
} |
928 |
err = rInt (that->rsp, OPENISIS_RSP_ERR, 0, 0); |
929 |
if (err) { |
930 |
return sMsg (ERR_IDIOT, "nGetResult(%s): response error %d", |
931 |
that->head.name, err); |
932 |
} |
933 |
numr = rInt (that->rsp, OPENISIS_RSP_NUMR, -1, 0); |
934 |
numt = rInt (that->rsp, OPENISIS_RSP_NUMT, -1, 0); |
935 |
if (0 > numr || 0 > numt) { |
936 |
return sMsg (ERR_IDIOT, "nGetResult(%s): no record count in response", |
937 |
that->head.name); |
938 |
} |
939 |
if (numr) { |
940 |
if (rowids) { |
941 |
*rowids = (int*) mAlloc (numr * sizeof (int)); |
942 |
if (! *rowids) { |
943 |
return sMsg (ERR_NOMEM, "nGetResult(%s): out of memory", |
944 |
that->head.name); |
945 |
} |
946 |
for (I = *rowids, j = pos = 0; numr > j; ++I, ++j) { |
947 |
*I = rInt (that->rsp, OPENISIS_COM_ROW, -1, &pos); |
948 |
if (0 > *I) { |
949 |
FREEROW; |
950 |
return sMsg (ERR_TRASH, |
951 |
"nGetResult(%s): missing rowid %d(%d)", |
952 |
that->head.name, j, numr); |
953 |
} |
954 |
} |
955 |
} |
956 |
|
957 |
if (recs) { |
958 |
*recs = (Rec**) mAlloc (numr * sizeof (Rec*)); |
959 |
if (! *recs) { |
960 |
FREEROW; |
961 |
return sMsg (ERR_NOMEM, "nGetResult(%s): out of memory", |
962 |
that->head.name); |
963 |
} |
964 |
memset (*recs, 0, numr * sizeof (Rec*)); |
965 |
R = *recs; |
966 |
I = rowids ? *rowids : 0; |
967 |
j = pos = 0; |
968 |
F = rGet (that->rsp, OPENISIS_COM_REC, &pos); |
969 |
if (! F) { |
970 |
sMsg (LOG_WARN, |
971 |
"nGetResult(%s): no records in response", |
972 |
that->head.name); |
973 |
FREEPTR (*recs); |
974 |
} |
975 |
else { |
976 |
--pos; |
977 |
while (numr > j) { |
978 |
*R = luti_unwrap (that->rsp, &pos, OPENISIS_COM_REC, |
979 |
that->rdb ? that->rdb->dbid : -1); |
980 |
if (! *R) { |
981 |
FREEROW; |
982 |
luti_free ((void**)*recs, j); |
983 |
*recs = 0; |
984 |
return sMsg (ERR_NOMEM, |
985 |
"nGetResult(%s): out of memory", that->head.name); |
986 |
} |
987 |
if (I) { |
988 |
(*R)->rowid = *I; |
989 |
++I; |
990 |
} |
991 |
++R; |
992 |
++j; |
993 |
} |
994 |
} |
995 |
} /* recs */ |
996 |
|
997 |
} /* numr */ |
998 |
|
999 |
if (db) { |
1000 |
*db = that->rdb; |
1001 |
} |
1002 |
if (tot) { |
1003 |
*tot = numt; |
1004 |
} |
1005 |
|
1006 |
return numr; |
1007 |
} |
1008 |
|