/[webpac]/trunk/openisis/ldsp.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/openisis/ldsp.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 239 - (show annotations)
Mon Mar 8 17:49:13 2004 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 14927 byte(s)
including openisis 0.9.0 into webpac tree

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: ldsp.c,v 1.32 2003/06/15 15:57:43 mawag Exp $
25 server side request processing.
26 */
27
28 #include <errno.h>
29 #include <limits.h> /* PATH_MAX */
30 #include <stdarg.h>
31 #include <stdio.h> /* vsnprintf */
32 #include <string.h>
33
34 #include "openisis.h"
35 #include "loi.h"
36 #include "ldb.h"
37 #include "ldsp.h"
38 #include "lfdt.h"
39 /* #include "lsv.h" */
40 #include "luti.h"
41
42 #ifdef WIN32
43 #define vsnprintf _vsnprintf
44 #endif
45
46 #define ISID 0
47 #define ISER 1
48 #define ITMS 2
49 #define SSTS 3
50
51 #define RSPVAR \
52 Db *dbh = 0; \
53 Rec *rsp = 0; \
54 int sdbid;
55
56 #define RSPADDR \
57 if (! rspa) { rspa = &rsp; }
58
59 #define RSPHEAD \
60 *rspa = rAddI (*rspa, OPENISIS_COM_SID, sst[ISID], !0); \
61 *rspa = rAddI (*rspa, OPENISIS_COM_SER, sst[ISER], !0);
62
63 #define RSPNOERR \
64 *rspa = rAddI (*rspa, OPENISIS_RSP_ERR, 0, !0);
65
66 #define RSPDB \
67 RADDS (*rspa, OPENISIS_COM_DBN, dbn, !0);
68
69 #define RSPFREE mFree (rsp);
70
71 #define GETDB(rname) \
72 sdbid = ldspGetDb (&dbh, sst, dbn); \
73 if (0 > sdbid) { \
74 int rt = _RqsError (sst, ERR_INVAL, rspa, cb, \
75 cld, rname, sst[ITMS] ? \
76 "db %s remounted" : "db %s not open", dbn); \
77 return rt; \
78 }
79
80 #define RSPFDT \
81 if (dbh->fdt) { \
82 *rspa = openIsisFFdt2Rec (dbh->fdt, *rspa, 0); \
83 } \
84 if (dbh->cfg) { \
85 *rspa = luti_wrap (*rspa, dbh->cfg, OPENISIS_COM_CFG); \
86 }
87
88 #define DELIVER \
89 if (*rspa) { \
90 int rt = 0; \
91 if (cb) { \
92 rt = (*cb) (rspa, cld); \
93 mFree (*rspa); \
94 } \
95 return rt; \
96 } \
97 return sMsg (ERR_NOMEM, "ldsp: deliver: rsp == 0");
98
99 #define UTF8REC(rec,inv,rname) \
100 if (openIsisEnc2Utf8 && dbh->cfg) { \
101 char ebuf[128]; \
102 char *enc = rString (dbh->cfg, OPENISIS_DENC, 0, ebuf, sizeof(ebuf)); \
103 if (enc && *enc && strcmp (enc, "utf-8")) { \
104 ldspUtf8Rec (&rec, enc, inv); \
105 } \
106 }
107
108 /* ************************************************************
109 */
110
111 static int ldspGetDb (Db **db, int sst[], const char *dbn) {
112 Db *dbh = nDbByName (stub0, dbn);
113 if (! dbh) {
114 sst[ITMS] = 0;
115 return -1;
116 }
117 if (sst[ITMS]) {
118 if (-1 == sst[ITMS] || /* dont want default of rInt call */
119 (dbh->tms && dbh->tms != sst[ITMS])
120 ) {
121 sst[ITMS] = dbh->tms;
122 return -1;
123 }
124 }
125 if (db) {
126 *db = dbh;
127 }
128 return dbh->dbid;
129 }
130
131 static int ldspUtf8Rec (Rec **rec, const char *enc, int invert) {
132 char buf[4096];
133 const char *dst;
134 Rec *res = 0;
135 Field *F, *E;
136 if (*rec && (*rec)->len) {
137 E = (*rec)->field + (*rec)->len;
138 for (F = (*rec)->field; E > F; ++F) {
139 if (0 == F->len || (1 == F->len && ! *(F->val))) {
140 RADDS (res, F->tag, "", !0);
141 }
142 else {
143 dst = (*openIsisEnc2Utf8) (enc,
144 F->val, F->len, buf, sizeof(buf), invert);
145 if (! dst) {
146 if (res) {
147 mFree (res);
148 }
149 return sMsg (ERR_TRASH,
150 "ldsp: cannot convert %s %s utf8: %.*s",
151 enc, (invert ? "from" : "to"), F->len, F->val);
152 }
153 RADDS (res, F->tag, dst, !0);
154 if (dst != buf && dst != F->val) {
155 (*openIsisEnc2Utf8) (0, dst, 0, 0, 0, 0);
156 }
157 }
158 if (! res) {
159 return sMsg (ERR_NOMEM, "ldsp: convert %s %s utf8: res == 0",
160 enc, (invert ? "from" : "to"));
161 }
162 }
163 res->rowid = (*rec)->rowid;
164 res->dbid = (*rec)->dbid;
165 mFree (*rec);
166 *rec = res;
167 }
168 return 0;
169 }
170
171 static int _RqsError (
172 int sst[], int err, Rec **rspa, LdspDlvCb *cb,
173 void *cld, const char *rname, const char *fmt, ...
174 ) {
175 Rec *rsp = 0;
176 char msg[OPENISIS_ERRMSGLEN];
177 va_list ap;
178 RSPADDR
179 RSPHEAD
180 sMsg (LOG_VERBOSE, "ldsp: _RqsError %s %x from %d/%d",
181 rname, err, sst[ISID], sst[ISER]);
182 if (sst[ITMS] && -1 != sst[ITMS]) {
183 *rspa = rAddI (*rspa, OPENISIS_COM_TMS, sst[ITMS], !0);
184 }
185 *rspa = rAddI (*rspa, OPENISIS_RSP_ERR, err, !0);
186 if (0 != fmt && 0 != *fmt) {
187 va_start (ap, fmt);
188 vsnprintf (msg, OPENISIS_ERRMSGLEN - 1, fmt, ap);
189 msg[OPENISIS_ERRMSGLEN - 1] = 0;
190 va_end (ap);
191 RADDS (*rspa, OPENISIS_RSP_MSG, msg, !0);
192 sMsg (LOG_WARN, "ldsp: err on rqs %s: %d(%x) - %s",
193 rname, err, err, msg);
194 }
195 else {
196 sMsg (LOG_WARN, "ldsp: err on rqs %s: %d(%x)",
197 rname, err, err);
198 }
199 DELIVER
200 }
201
202 static int _RqsLsDb (
203 int sst[], Rec **rspa, LdspDlvCb *cb, void *cld
204 ) {
205 Rec *rsp = 0;
206 Schema *sc;
207 char *n;
208 int j;
209 sc = nSchema (stub0);
210 if (! sc) {
211 j = _RqsError (sst, ERR_BADF, rspa, cb, cld,
212 "lsdb", "local schema not initialized");
213 return j;
214 }
215 RSPADDR
216 RSPHEAD
217 RSPNOERR
218 sMsg (LOG_VERBOSE, "ldsp: _RqsLsDb from %d/%d", sst[ISID], sst[ISER]);
219 for (j = 0; sc->ndbs > j; ++j) {
220 if (*(n = sc->dbs[j]->name)) {
221 RADDS (*rspa, OPENISIS_COM_DBN, n, !0);
222 }
223 }
224 DELIVER
225 }
226
227 static int _RqsEval (
228 int sst[], Rec *cmd, Rec **rspa, LdspDlvCb *cb, void *cld
229 ) {
230 Rec *res = 0;
231 Rec *rsp = 0;
232 int j;
233 if (! openIsisEval) {
234 j = _RqsError (sst, ERR_IDIOT, rspa, cb, cld,
235 "eval", "server has no eval function");
236 mFree (cmd);
237 return j;
238 }
239 j = (*openIsisEval) (cmd, &res);
240 mFree (cmd);
241 RSPADDR
242 RSPHEAD
243 *rspa = rAddI (*rspa, OPENISIS_RSP_ERR, j, !0);
244 if (res) {
245 *rspa = rAddI (*rspa, OPENISIS_RSP_NUMT, 1, !0);
246 *rspa = rAddI (*rspa, OPENISIS_RSP_NUMR, 1, !0);
247 *rspa = rAddI (*rspa, OPENISIS_COM_ROW, 0, !0);
248 *rspa = luti_wrap (*rspa, res, OPENISIS_COM_REC);
249 mFree (res);
250 }
251 else {
252 *rspa = rAddI (*rspa, OPENISIS_RSP_NUMT, 0, !0);
253 *rspa = rAddI (*rspa, OPENISIS_RSP_NUMR, 0, !0);
254 }
255 DELIVER
256 }
257
258 static int _RqsOpen (
259 int sst[], const char *dbn, Rec *dbpar, Fdt *fdt,
260 Rec **rspa, LdspDlvCb *cb, void *cld
261 ) {
262 #define STRERRNOLEN 128
263 RSPVAR
264 Schema *sc;
265 char msg[STRERRNOLEN];
266 sst[ITMS] = 0;
267 sc = nSchema (stub0);
268 if (! sc) {
269 int rt = _RqsError (sst, ERR_BADF, rspa, cb, cld,
270 "open", "%s: local schema not initialized", dbn);
271 mFree (dbpar);
272 return rt;
273 }
274 sMsg (LOG_VERBOSE, "ldsp: _RqsOpen %s from %d/%d",
275 dbn, sst[ISID], sst[ISER]);
276 errno = 0;
277 dbh = cDOpen (dbn, dbpar, sc->cfg, fdt);
278 if (! dbh) {
279 int rt;
280 strncpy (msg, strerror (errno), STRERRNOLEN - 1)
281 [STRERRNOLEN - 1] = 0;
282 rt = _RqsError (sst, ERR_BADF, rspa, cb, cld,
283 "open", "%s: %s", dbn, msg);
284 mFree (dbpar);
285 return rt;
286 }
287 sdbid = dbh->dbid;
288 dbn = dbh->name;
289 RSPADDR
290 RSPHEAD
291 RSPNOERR
292 RSPDB
293 *rspa = rAddI (*rspa, OPENISIS_RSP_DBID, sdbid, !0);
294 *rspa = rAddI (*rspa, OPENISIS_COM_TMS, dbh->tms, !0);
295 mFree (dbpar);
296 DELIVER
297 }
298
299 static int _RqsClose (
300 int sst[], const char *dbn, Rec **rspa, LdspDlvCb *cb, void *cld
301 ) {
302 RSPVAR
303 int err;
304 GETDB("close")
305 sMsg (LOG_VERBOSE, "ldsp: _RqsClose %s from %d/%d",
306 dbn, sst[ISID], sst[ISER]);
307 err = cDClose (sdbid);
308 RSPADDR
309 RSPHEAD
310 *rspa = rAddI (*rspa, OPENISIS_RSP_DBID, sdbid, !0);
311 *rspa = rAddI (*rspa, OPENISIS_RSP_ERR, err, !0);
312 RSPDB
313 DELIVER
314 }
315
316 static int _RqsMount (
317 int sst[], const char *dbn, Rec **rspa, LdspDlvCb *cb, void *cld
318 ) {
319 RSPVAR
320 GETDB("mount")
321 RSPADDR
322 RSPHEAD
323 sMsg (LOG_VERBOSE, "ldsp: _RqsMount %s from %d/%d",
324 dbn, sst[ISID], sst[ISER]);
325 RSPNOERR
326 RSPDB
327 RSPFDT
328 DELIVER
329 }
330
331 static int _RqsMaxrow (
332 int sst[], const char *dbn, int flags,
333 Rec **rspa, LdspDlvCb *cb, void *cld
334 ) {
335 RSPVAR
336 int maxrow;
337 GETDB("maxrow")
338 maxrow = dMaxId (sdbid);
339 if (0 > maxrow) {
340 int rt = _RqsError (sst, ERR_TRASH, rspa, cb, cld, "maxrow",
341 "no maxrow for %s", dbn);
342 RSPFREE
343 return rt;
344 }
345 RSPADDR
346 RSPHEAD
347 sMsg (LOG_VERBOSE, "ldsp: _RqsMaxrow %s from %d/%d",
348 dbn, sst[ISID], sst[ISER]);
349 RSPNOERR
350 RSPDB
351 if (OPENISIS_RQSF_MNT & flags) {
352 RSPFDT
353 }
354 *rspa = rAddI (*rspa, OPENISIS_COM_ROW, maxrow, !0);
355 DELIVER
356 }
357
358 static int _RqsQuery (
359 int sst[], const char *dbn, const char *key, int mode, int skip,
360 int size, int flags, Rec **rspa, LdspDlvCb *cb, void *cld
361 ) {
362 RSPVAR
363 Set set;
364 Rec *rec;
365 int lrt;
366 int j;
367 int rdr = OPENISIS_RQSF_QRR & flags;
368 GETDB("query")
369 sMsg (LOG_VERBOSE, "ldsp: _RqsQuery %s from %d/%d",
370 dbn, sst[ISID], sst[ISER]);
371 set.len = 0; /* input */
372 lrt = dQuery (&set, sdbid, key, mode, skip);
373 if (0 > lrt) {
374 int rt = _RqsError (sst, ERR_TRASH, rspa, cb, cld, "query",
375 "%d,%s = %d", sdbid, key, lrt);
376 return rt;
377 }
378 RSPADDR
379 RSPHEAD
380 RSPNOERR
381 RSPDB
382 if (OPENISIS_RQSF_MNT & flags) {
383 RSPFDT
384 }
385 *rspa = rAddI (*rspa, OPENISIS_RSP_NUMT, lrt, !0);
386 if (0 < size && lrt > size) {
387 lrt = size;
388 }
389 *rspa = rAddI (*rspa, OPENISIS_RSP_NUMR, lrt, !0);
390 for (j = 0; lrt > j; ++j) {
391 *rspa = rAddI (*rspa, OPENISIS_COM_ROW, set.id[j], !0);
392 }
393 if (rdr) {
394 for (j = 0; *rspa && lrt > j; ++j) {
395 rec = dRead (sdbid, set.id[j]);
396 if (rec) {
397 UTF8REC (rec, 0, "query")
398 }
399 else {
400 sMsg (ERR_TRASH | LOG_WARN,
401 "db %s: non-existent mfn %d for key %s",
402 dbn, set.id[j], key);
403 rec = rDup (0, 0, 0);
404 }
405 *rspa = luti_wrap (*rspa, rec, OPENISIS_COM_REC);
406 mFree (rec);
407 }
408 }
409 DELIVER
410 }
411
412 static int _RqsRead (
413 int sst[], const char *dbn, int row, int flags,
414 Rec **rspa, LdspDlvCb *cb, void *cld
415 ) {
416 RSPVAR
417 Rec *rec;
418 GETDB("read")
419 RSPADDR
420 RSPHEAD
421 sMsg (LOG_VERBOSE, "ldsp: _RqsRead %s %d from %d/%d",
422 dbn, row, sst[ISID], sst[ISER]);
423 RSPNOERR
424 RSPDB
425 if (OPENISIS_RQSF_MNT & flags) {
426 RSPFDT
427 }
428 rec = dRead (sdbid, row);
429 if (rec) {
430 *rspa = rAddI (*rspa, OPENISIS_RSP_NUMT, 1, !0);
431 *rspa = rAddI (*rspa, OPENISIS_RSP_NUMR, 1, !0);
432 *rspa = rAddI (*rspa, OPENISIS_COM_ROW, row, !0);
433 UTF8REC (rec, 0, "read")
434 *rspa = luti_wrap (*rspa, rec, OPENISIS_COM_REC);
435 mFree (rec);
436 }
437 else {
438 *rspa = rAddI (*rspa, OPENISIS_RSP_NUMT, 0, !0);
439 *rspa = rAddI (*rspa, OPENISIS_RSP_NUMR, 0, !0);
440 }
441 DELIVER
442 }
443
444 static int _RqsUpdate (
445 int sst[], const char *dbn, int row, Rec *rec, Rec *idx, int flags,
446 Rec **rspa, LdspDlvCb *cb, void *cld
447 ) {
448 RSPVAR
449 int rtw;
450 GETDB("update")
451 sMsg (LOG_VERBOSE, "ldsp: _RqsUpdate %s %d from %d/%d",
452 dbn, row, sst[ISID], sst[ISER]);
453 if (rec) {
454 rec->rowid = row;
455 rec->dbid = sdbid;
456 UTF8REC (rec, !0, "update")
457 }
458 rtw = dWritex (sdbid, rec, idx);
459 if (rtw) {
460 rtw = _RqsError (sst, ERR_TRASH, rspa, cb, cld,
461 "update", "write error %d", rtw);
462 mFree (rec);
463 mFree (idx);
464 return rtw;
465 }
466 RSPADDR
467 RSPHEAD
468 RSPNOERR
469 RSPDB
470 if (OPENISIS_RQSF_MNT & flags) {
471 RSPFDT
472 }
473 if (rec) {
474 row = rec->rowid;
475 mFree (rec);
476 }
477 mFree (idx);
478 *rspa = rAddI (*rspa, OPENISIS_COM_ROW, row, !0);
479 DELIVER
480 }
481
482 static int _RqsDelete (
483 int sst[], const char *dbn, int row, int flags,
484 Rec **rspa, LdspDlvCb *cb, void *cld
485 ) {
486 (void)flags;
487 sMsg (LOG_VERBOSE, "ldsp: _RqsDelete %s %d from %d/%d",
488 dbn, row, sst[ISID], sst[ISER]);
489 return _RqsError (sst, ERR_TRASH, rspa, cb, cld, "delete",
490 "request not implemented yet");
491 }
492
493 /* ************************************************************
494 package functions
495 */
496
497 int ldspProcess (Rec *rqs, Rec **rspa, LdspDlvCb *cb, void *cld) {
498 char buf[PATH_MAX];
499 char *dbn = 0;
500 int sst[SSTS];
501 int rtyp;
502 int flags = 0;
503
504 if (0 == rqs) {
505 return sMsg (ERR_IDIOT, "ldspProcess: no request");
506 }
507 if (0 == rspa && 0 == cb) {
508 return sMsg (ERR_IDIOT, "ldspProcess: no callback");
509 }
510
511 rtyp = rInt (rqs, OPENISIS_RQS_TYPE, -1, 0);
512 sst[ISID] = rInt (rqs, OPENISIS_COM_SID, -1, 0);
513 sst[ISER] = rInt (rqs, OPENISIS_COM_SER, -1, 0);
514 sst[ITMS] = rInt (rqs, OPENISIS_COM_TMS, -1, 0);
515
516 if (OPENISIS_RQST_LSDB != rtyp &&
517 OPENISIS_RQST_EVAL != rtyp
518 ) {
519 dbn = rString (rqs, OPENISIS_COM_DBN, 0, buf, sizeof(buf));
520 if (!dbn) {
521 i2a (buf, rtyp);
522 return _RqsError (sst, ERR_INVAL, rspa, cb, cld, buf,
523 "no db name given");
524 }
525 flags = rInt (rqs, OPENISIS_RQS_FLG, 0, 0);
526 }
527
528 switch (rtyp) {
529
530 case OPENISIS_RQST_LSDB:
531 return _RqsLsDb (sst, rspa, cb, cld);
532
533 case OPENISIS_RQST_OPEN: {
534 Rec *dbpar = luti_unwrap (rqs, 0, OPENISIS_COM_CFG, -1);
535 Fdt *fdt = fRec2Fdt (rqs);
536 return _RqsOpen (sst, dbn, dbpar, fdt, rspa, cb, cld);
537 }
538
539 case OPENISIS_RQST_CLOS:
540 return _RqsClose (sst, dbn, rspa, cb, cld);
541
542 case OPENISIS_RQST_MNT:
543 return _RqsMount (sst, dbn, rspa, cb, cld);
544
545 case OPENISIS_RQST_MROW:
546 return _RqsMaxrow (sst, dbn, flags, rspa, cb, cld);
547
548 case OPENISIS_RQST_QRY: {
549 char kybuf[OPENISIS_QRY_KEYLEN];
550 char *key;
551 int mode, skip, size;
552 key = rString (rqs, OPENISIS_RQS_KEY, 0, kybuf, OPENISIS_QRY_KEYLEN);
553 mode = rInt (rqs, OPENISIS_RQS_QMOD, -1, 0);
554 skip = rInt (rqs, OPENISIS_RQS_SKIP, 0, 0);
555 size = rInt (rqs, OPENISIS_RQS_SIZE, -1, 0);
556 if (0 > mode || 0 == key) {
557 return _RqsError (sst, ERR_INVAL, rspa, cb, cld, "query",
558 "missing mode or key");
559 }
560 return _RqsQuery (sst, dbn, key,
561 mode, skip, size, flags, rspa, cb, cld);
562 }
563
564 case OPENISIS_RQST_READ: {
565 int rowid;
566 rowid = rInt (rqs, OPENISIS_COM_ROW, -1, 0);
567 if (0 > rowid) {
568 return _RqsError (sst, ERR_INVAL, rspa, cb, cld, "read",
569 "missing rowid");
570 }
571 return _RqsRead (sst, dbn, rowid, flags, rspa, cb, cld);
572 }
573
574 case OPENISIS_RQST_INS:
575 case OPENISIS_RQST_UPD: {
576 Rec *rec, *idx;
577 int rowid = 0;
578 int ins = rtyp == OPENISIS_RQST_INS;
579 rec = luti_unwrap (rqs, 0, OPENISIS_COM_REC, -1);
580 idx = luti_unwrap (rqs, 0, OPENISIS_RQS_IDX, -1);
581 if (!(rec || idx)) {
582 return _RqsError (sst, ERR_INVAL, rspa, cb, cld,
583 "update", "missing record or index");
584 }
585 rowid = rInt (rqs, OPENISIS_COM_ROW, 0, 0);
586 if (! ins && 0 >= rowid) {
587 return _RqsError (sst, ERR_INVAL, rspa, cb, cld,
588 "update", "missing rowid");
589 }
590 return _RqsUpdate (sst, dbn, rowid, rec, idx, flags, rspa, cb, cld);
591 }
592
593 case OPENISIS_RQST_DEL: {
594 int rowid;
595 rowid = rInt (rqs, OPENISIS_COM_ROW, -1, 0);
596 if (0 > rowid) {
597 return _RqsError (sst, ERR_INVAL, rspa, cb, cld, "delete",
598 "missing rowid");
599 }
600 return _RqsDelete (sst, dbn, rowid, flags, rspa, cb, cld);
601 }
602
603 case OPENISIS_RQST_EVAL: {
604 Rec *rec;
605 rec = luti_unwrap (rqs, 0, OPENISIS_COM_REC, -1);
606 if (! rec) {
607 return _RqsError (sst, ERR_INVAL, rspa, cb, cld,
608 "eval", "missing command record");
609 }
610 return _RqsEval (sst, rec, rspa, cb, cld);
611 }
612
613 } /* switch */
614
615 i2a (buf, rtyp);
616 return _RqsError (sst, ERR_INVAL, rspa, cb, cld, buf,
617 "unrecognized request type");
618 } /* ldspProcess */
619

  ViewVC Help
Powered by ViewVC 1.1.26