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
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.
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.
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
20 see README for more information
24 $Id: ldsp.c,v 1.32 2003/06/15 15:57:43 mawag Exp $
25 server side request processing.
29 #include <limits.h> /* PATH_MAX */
31 #include <stdio.h> /* vsnprintf */
39 /* #include "lsv.h" */
43 #define vsnprintf _vsnprintf
57 if (! rspa) { rspa = &rsp; }
60 *rspa = rAddI (*rspa, OPENISIS_COM_SID, sst[ISID], !0); \
61 *rspa = rAddI (*rspa, OPENISIS_COM_SER, sst[ISER], !0);
64 *rspa = rAddI (*rspa, OPENISIS_RSP_ERR, 0, !0);
67 RADDS (*rspa, OPENISIS_COM_DBN, dbn, !0);
69 #define RSPFREE mFree (rsp);
71 #define GETDB(rname) \
72 sdbid = ldspGetDb (&dbh, sst, dbn); \
74 int rt = _RqsError (sst, ERR_INVAL, rspa, cb, \
75 cld, rname, sst[ITMS] ? \
76 "db %s remounted" : "db %s not open", dbn); \
82 *rspa = openIsisFFdt2Rec (dbh->fdt, *rspa, 0); \
85 *rspa = luti_wrap (*rspa, dbh->cfg, OPENISIS_COM_CFG); \
92 rt = (*cb) (rspa, cld); \
97 return sMsg (ERR_NOMEM, "ldsp: deliver: rsp == 0");
99 #define UTF8REC(rec,inv,rname) \
100 if (openIsisEnc2Utf8 && dbh->cfg) { \
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); \
108 /* ************************************************************
111 static int ldspGetDb (Db **db, int sst[], const char *dbn) {
112 Db *dbh = nDbByName (stub0, dbn);
118 if (-1 == sst[ITMS] || /* dont want default of rInt call */
119 (dbh->tms && dbh->tms != sst[ITMS])
121 sst[ITMS] = dbh->tms;
131 static int ldspUtf8Rec (Rec **rec, const char *enc, int invert) {
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);
143 dst = (*openIsisEnc2Utf8) (enc,
144 F->val, F->len, buf, sizeof(buf), invert);
149 return sMsg (ERR_TRASH,
150 "ldsp: cannot convert %s %s utf8: %.*s",
151 enc, (invert ? "from" : "to"), F->len, F->val);
153 RADDS (res, F->tag, dst, !0);
154 if (dst != buf && dst != F->val) {
155 (*openIsisEnc2Utf8) (0, dst, 0, 0, 0, 0);
159 return sMsg (ERR_NOMEM, "ldsp: convert %s %s utf8: res == 0",
160 enc, (invert ? "from" : "to"));
163 res->rowid = (*rec)->rowid;
164 res->dbid = (*rec)->dbid;
171 static int _RqsError (
172 int sst[], int err, Rec **rspa, LdspDlvCb *cb,
173 void *cld, const char *rname, const char *fmt, ...
176 char msg[OPENISIS_ERRMSGLEN];
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);
185 *rspa = rAddI (*rspa, OPENISIS_RSP_ERR, err, !0);
186 if (0 != fmt && 0 != *fmt) {
188 vsnprintf (msg, OPENISIS_ERRMSGLEN - 1, fmt, ap);
189 msg[OPENISIS_ERRMSGLEN - 1] = 0;
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);
196 sMsg (LOG_WARN, "ldsp: err on rqs %s: %d(%x)",
202 static int _RqsLsDb (
203 int sst[], Rec **rspa, LdspDlvCb *cb, void *cld
209 sc = nSchema (stub0);
211 j = _RqsError (sst, ERR_BADF, rspa, cb, cld,
212 "lsdb", "local schema not initialized");
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);
227 static int _RqsEval (
228 int sst[], Rec *cmd, Rec **rspa, LdspDlvCb *cb, void *cld
233 if (! openIsisEval) {
234 j = _RqsError (sst, ERR_IDIOT, rspa, cb, cld,
235 "eval", "server has no eval function");
239 j = (*openIsisEval) (cmd, &res);
243 *rspa = rAddI (*rspa, OPENISIS_RSP_ERR, j, !0);
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);
252 *rspa = rAddI (*rspa, OPENISIS_RSP_NUMT, 0, !0);
253 *rspa = rAddI (*rspa, OPENISIS_RSP_NUMR, 0, !0);
258 static int _RqsOpen (
259 int sst[], const char *dbn, Rec *dbpar, Fdt *fdt,
260 Rec **rspa, LdspDlvCb *cb, void *cld
262 #define STRERRNOLEN 128
265 char msg[STRERRNOLEN];
267 sc = nSchema (stub0);
269 int rt = _RqsError (sst, ERR_BADF, rspa, cb, cld,
270 "open", "%s: local schema not initialized", dbn);
274 sMsg (LOG_VERBOSE, "ldsp: _RqsOpen %s from %d/%d",
275 dbn, sst[ISID], sst[ISER]);
277 dbh = cDOpen (dbn, dbpar, sc->cfg, fdt);
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);
293 *rspa = rAddI (*rspa, OPENISIS_RSP_DBID, sdbid, !0);
294 *rspa = rAddI (*rspa, OPENISIS_COM_TMS, dbh->tms, !0);
299 static int _RqsClose (
300 int sst[], const char *dbn, Rec **rspa, LdspDlvCb *cb, void *cld
305 sMsg (LOG_VERBOSE, "ldsp: _RqsClose %s from %d/%d",
306 dbn, sst[ISID], sst[ISER]);
307 err = cDClose (sdbid);
310 *rspa = rAddI (*rspa, OPENISIS_RSP_DBID, sdbid, !0);
311 *rspa = rAddI (*rspa, OPENISIS_RSP_ERR, err, !0);
316 static int _RqsMount (
317 int sst[], const char *dbn, Rec **rspa, LdspDlvCb *cb, void *cld
323 sMsg (LOG_VERBOSE, "ldsp: _RqsMount %s from %d/%d",
324 dbn, sst[ISID], sst[ISER]);
331 static int _RqsMaxrow (
332 int sst[], const char *dbn, int flags,
333 Rec **rspa, LdspDlvCb *cb, void *cld
338 maxrow = dMaxId (sdbid);
340 int rt = _RqsError (sst, ERR_TRASH, rspa, cb, cld, "maxrow",
341 "no maxrow for %s", dbn);
347 sMsg (LOG_VERBOSE, "ldsp: _RqsMaxrow %s from %d/%d",
348 dbn, sst[ISID], sst[ISER]);
351 if (OPENISIS_RQSF_MNT & flags) {
354 *rspa = rAddI (*rspa, OPENISIS_COM_ROW, maxrow, !0);
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
367 int rdr = OPENISIS_RQSF_QRR & flags;
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);
374 int rt = _RqsError (sst, ERR_TRASH, rspa, cb, cld, "query",
375 "%d,%s = %d", sdbid, key, lrt);
382 if (OPENISIS_RQSF_MNT & flags) {
385 *rspa = rAddI (*rspa, OPENISIS_RSP_NUMT, lrt, !0);
386 if (0 < size && lrt > size) {
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);
394 for (j = 0; *rspa && lrt > j; ++j) {
395 rec = dRead (sdbid, set.id[j]);
397 UTF8REC (rec, 0, "query")
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);
405 *rspa = luti_wrap (*rspa, rec, OPENISIS_COM_REC);
412 static int _RqsRead (
413 int sst[], const char *dbn, int row, int flags,
414 Rec **rspa, LdspDlvCb *cb, void *cld
421 sMsg (LOG_VERBOSE, "ldsp: _RqsRead %s %d from %d/%d",
422 dbn, row, sst[ISID], sst[ISER]);
425 if (OPENISIS_RQSF_MNT & flags) {
428 rec = dRead (sdbid, row);
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);
438 *rspa = rAddI (*rspa, OPENISIS_RSP_NUMT, 0, !0);
439 *rspa = rAddI (*rspa, OPENISIS_RSP_NUMR, 0, !0);
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
451 sMsg (LOG_VERBOSE, "ldsp: _RqsUpdate %s %d from %d/%d",
452 dbn, row, sst[ISID], sst[ISER]);
456 UTF8REC (rec, !0, "update")
458 rtw = dWritex (sdbid, rec, idx);
460 rtw = _RqsError (sst, ERR_TRASH, rspa, cb, cld,
461 "update", "write error %d", rtw);
470 if (OPENISIS_RQSF_MNT & flags) {
478 *rspa = rAddI (*rspa, OPENISIS_COM_ROW, row, !0);
482 static int _RqsDelete (
483 int sst[], const char *dbn, int row, int flags,
484 Rec **rspa, LdspDlvCb *cb, void *cld
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");
493 /* ************************************************************
497 int ldspProcess (Rec *rqs, Rec **rspa, LdspDlvCb *cb, void *cld) {
505 return sMsg (ERR_IDIOT, "ldspProcess: no request");
507 if (0 == rspa && 0 == cb) {
508 return sMsg (ERR_IDIOT, "ldspProcess: no callback");
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);
516 if (OPENISIS_RQST_LSDB != rtyp &&
517 OPENISIS_RQST_EVAL != rtyp
519 dbn = rString (rqs, OPENISIS_COM_DBN, 0, buf, sizeof(buf));
522 return _RqsError (sst, ERR_INVAL, rspa, cb, cld, buf,
525 flags = rInt (rqs, OPENISIS_RQS_FLG, 0, 0);
530 case OPENISIS_RQST_LSDB:
531 return _RqsLsDb (sst, rspa, cb, cld);
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);
539 case OPENISIS_RQST_CLOS:
540 return _RqsClose (sst, dbn, rspa, cb, cld);
542 case OPENISIS_RQST_MNT:
543 return _RqsMount (sst, dbn, rspa, cb, cld);
545 case OPENISIS_RQST_MROW:
546 return _RqsMaxrow (sst, dbn, flags, rspa, cb, cld);
548 case OPENISIS_RQST_QRY: {
549 char kybuf[OPENISIS_QRY_KEYLEN];
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");
560 return _RqsQuery (sst, dbn, key,
561 mode, skip, size, flags, rspa, cb, cld);
564 case OPENISIS_RQST_READ: {
566 rowid = rInt (rqs, OPENISIS_COM_ROW, -1, 0);
568 return _RqsError (sst, ERR_INVAL, rspa, cb, cld, "read",
571 return _RqsRead (sst, dbn, rowid, flags, rspa, cb, cld);
574 case OPENISIS_RQST_INS:
575 case OPENISIS_RQST_UPD: {
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);
582 return _RqsError (sst, ERR_INVAL, rspa, cb, cld,
583 "update", "missing record or index");
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");
590 return _RqsUpdate (sst, dbn, rowid, rec, idx, flags, rspa, cb, cld);
593 case OPENISIS_RQST_DEL: {
595 rowid = rInt (rqs, OPENISIS_COM_ROW, -1, 0);
597 return _RqsError (sst, ERR_INVAL, rspa, cb, cld, "delete",
600 return _RqsDelete (sst, dbn, rowid, flags, rspa, cb, cld);
603 case OPENISIS_RQST_EVAL: {
605 rec = luti_unwrap (rqs, 0, OPENISIS_COM_REC, -1);
607 return _RqsError (sst, ERR_INVAL, rspa, cb, cld,
608 "eval", "missing command record");
610 return _RqsEval (sst, rec, rspa, cb, cld);
616 return _RqsError (sst, ERR_INVAL, rspa, cb, cld, buf,
617 "unrecognized request type");