Annotation of freem/src/global_dispatch.c, revision 1.1.1.1
1.1 snw 1: /*
2: * *
3: * * *
4: * * *
5: * ***************
6: * * * * *
7: * * MUMPS *
8: * * * * *
9: * ***************
10: * * *
11: * * *
12: * *
13: *
14: * global_dispatch.c
15: * global handler dispatch module
16: *
17: *
18: * Author: Serena Willis <jpw@coherent-logic.com>
19: * Copyright (C) 1998 MUG Deutschland
20: * Copyright (C) 2020 Coherent Logic Development LLC
21: *
22: *
23: * This file is part of FreeM.
24: *
25: * FreeM is free software: you can redistribute it and/or modify
26: * it under the terms of the GNU Affero Public License as published by
27: * the Free Software Foundation, either version 3 of the License, or
28: * (at your option) any later version.
29: *
30: * FreeM is distributed in the hope that it will be useful,
31: * but WITHOUT ANY WARRANTY; without even the implied warranty of
32: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33: * GNU Affero Public License for more details.
34: *
35: * You should have received a copy of the GNU Affero Public License
36: * along with FreeM. If not, see <https://www.gnu.org/licenses/>.
37: *
38: **/
39:
40: #include <stdlib.h>
41: #include <string.h>
42: #include <unistd.h>
43: #include <ctype.h>
44:
45: #include "mpsdef.h"
46: #include "mref.h"
47: #include "events.h"
48: #include "config.h"
49: #include "namespace.h"
50: #include "transact.h"
51: #include "mdebug.h"
52: #include "journal.h"
53: #include "iftab.h"
54: #include "shmmgr.h"
55:
56: void (*gbl_u)(short, char *, char *);
57: void (*gbl_s)(short, char *, char *);
58:
59: void global_set_engine(char ns, char *engine)
60: {
61:
62:
63: if ((strcmp (engine, "BUILTIN") != 0) && (strcmp (engine, "BERKELEYDB") != 0)) {
64:
65: if (strcmp (engine, "NICKELBACK") == 0) {
66: char *j;
67: printf ("\r\nERROR: please go burn your CD collection in fire. Here, have a segfault...\r\n");
68:
69: j[2] = '\201';
70: }
71:
72: printf ("\r\nERROR: '%s' is not a valid global storage engine\r\n", engine);
73: merr_raise (M38);
74:
75: return;
76:
77: }
78:
79: switch (ns) {
80:
81: case 'u':
82: strcpy (gbl_u_engine, engine);
83:
84: if (strcmp (engine, "BUILTIN") == 0) {
85: gbl_u = &global_bltin;
86: }
87: #if defined(GVH_BDB)
88: else if (strcmp (engine, "BERKELEYDB") == 0) {
89: gbl_u = &global_bdb;
90: }
91: #endif
92: else {
93: fprintf (stderr, "global_set_engine: invalid global handler '%s' or FreeM built without '%s' global handler support.\r\n", engine, engine);
94: fprintf (stderr, "global set_engine: defaulting to 'BUILTIN' global handler for namespace '%s'.\r\n", nsname);
95: gbl_u = &global_bltin;
96: }
97:
98: break;
99:
100: case 's':
101: strcpy (gbl_s_engine, engine);
102:
103: if (strcmp (engine, "BUILTIN") == 0) {
104: gbl_s = &global_bltin;
105: }
106: #if defined(GVH_BDB)
107: else if (strcmp (engine, "BERKELEYDB") == 0) {
108: gbl_s = &global_bdb;
109: }
110: #endif
111: else {
112: fprintf (stderr, "global_set_engine: invalid global handler '%s' or FreeM built without '%s' global handler support.\r\n", engine, engine);
113: fprintf (stderr, "global set_engine: defaulting to 'BUILTIN' global handler for namespace 'SYSTEM'.\r\n");
114: gbl_s = &global_bltin;
115: }
116:
117: break;
118:
119: }
120:
121: //ssvn_job_update ();
122:
123: merr_raise (OK);
124: return;
125:
126: }
127:
128: void global (short action, char *key, char *data)
129: {
130:
131: int ierr_sav = OK;
132:
133: char *ptr;
134: char name[256];
135: char old_gloplib[PATHLEN];
136: register int i = 0;
137: register int j = 0;
138: register char ch;
139:
140: char *old_ns;
141: char *old_value;
142: char *new_value;
143: char *tk_buf;
144: char *mapk_buf;
145: char *mapd_buf;
146: freem_ref_t *r;
147: short extref_flg;
148: short mapped_flg;
149:
150: /* variables for transaction-in-flight symbol table */
151: iftab *ift;
152: char tmpd[256];
153:
154: old_ns = (char *) malloc (STRLEN * sizeof (char));
155: NULLPTRCHK(old_ns,"global");
156:
157: old_value = (char *) malloc (STRLEN * sizeof (char));
158: NULLPTRCHK(old_value,"global");
159:
160: new_value = (char *) malloc (STRLEN * sizeof (char));
161: NULLPTRCHK(new_value,"global");
162:
163: tk_buf = (char *) malloc (STRLEN * sizeof (char));
164: NULLPTRCHK(tk_buf,"global");
165:
166: mapk_buf = (char *) malloc (STRLEN * sizeof (char));
167: NULLPTRCHK(mapk_buf,"global");
168:
169: mapd_buf = (char *) malloc (STRLEN * sizeof (char));
170: NULLPTRCHK(mapd_buf,"global");
171:
172: r = (freem_ref_t *) malloc (sizeof (freem_ref_t));
173: NULLPTRCHK(r,"global");
174:
175: extref_flg = FALSE;
176: mapped_flg = FALSE;
177:
178: ptr = key;
179: if (key[1] != '$') {
180: while ((shm_config->hdr->tp_owner != pid) && (shm_config->hdr->tp_owner != 0)) {
181: sleep (1);
182: }
183: }
184:
185: stcpy (tk_buf, key);
186:
187: if (key[1] != '$') frm_process_alias (key);
188:
189: if (key[1] != '$') {
190: /* process mappings */
191: ierr_sav = OK;
192:
193: while ((ch = *(ptr++)) != DELIM && ch != EOL && i < 256) {
194: name[i++] = ch;
195: }
196:
197: name[i] = '\0';
198:
199: snprintf (mapk_buf, STRLEN - 1, "^$SYSTEM\202MAPPINGS\202GLOBAL\202%s\201", name);
200: global (get_sym, mapk_buf, mapd_buf);
201:
202: stcnv_m2c (mapd_buf);
203:
204: if (merr () == OK) {
205: mapped_flg = TRUE;
206: strncpy (old_ns, nsname, STRLEN - 1);
207: set_namespace (mapd_buf, 0);
208: strncpy (old_gloplib, gloplib, PATHLEN - 1);
209: strncpy (gloplib, glopath, PATHLEN - 1);
210: }
211: else {
212: merr_raise (OK);
213: }
214: }
215:
216: if (dbg_enable_watch && (action == set_sym)) dbg_fire_watch (key);
217:
218: if ((jnl_enabled == TRUE) && (key[1] != '$') && (tp_committing == FALSE)) {
219: switch (action) {
220:
221: case set_sym:
222: jnl_ent_write (JNLA_SET, key, data);
223: break;
224:
225: case kill_sym:
226: case killone:
227: jnl_ent_write (JNLA_KILL, key, data);
228: break;
229:
230: }
231: }
232:
233: /* If we are writing to a global in a transaction but not committing it,
234: queue up the operation at the current transaction level.*/
235: if ((tp_level > 0) && (action == set_sym ||
236: action == kill_sym ||
237: action == killone ||
238: action == merge_sym) && (tp_committing == FALSE)) {
239:
240: if (key[1] != '$') {
241: tp_add_op (FALSE, action, key, data);
242:
243: merr_raise (OK);
244: return;
245: }
246:
247: }
248:
249: /* in a transaction and retrieving */
250: if ((tp_level > 0) && (action == get_sym)) {
251:
252: /* check transactions-in-flight symbol table */
253: ift = iftab_retrieve (key, tmpd);
254:
255: if (ift != NULL) {
256:
257: if (ift->killed == TRUE) {
258: merr_raise (M7);
259: }
260: else {
261: stcpy (data, ift->data);
262: merr_raise (OK);
263: }
264:
265: return;
266: }
267:
268: /* if we got here, the node referenced by "key" has not been
269: modified in the current transaction, so we can proceed to
270: the normal disk block retrieval. */
271: }
272:
273:
274: mref_init (r, MREF_RT_GLOBAL, "^DUMMY");
275: internal_to_mref (r, key);
276:
277: if (rtn_dialect () == D_M77) {
278:
279: for (i = 0; i < r->subscript_count; i++) {
280: for (j = 0; j < strlen (r->subscripts[i]); j++) {
281:
282: ch = r->subscripts[i][j];
283:
284: if (!isdigit (ch)) {
285: merr_raise (NOSTAND);
286: return;
287: }
288:
289: }
290: }
291:
292: }
293:
294:
295: if ((r->name[1] == '|')) {
296:
297: /* this is an mdc-style extended reference */
298:
299: char old_code[512];
300: char *old_codptr;
301: char newns[256];
302: register int i = 0;
303: char *nsstart;
304: char *nssave;
305: char ch;
306: char *subprt;
307: extref_flg = TRUE;
308:
309: /* save off current interpreter state (code and codptr)
310: so we can call expr() without losing the plot */
311: stcpy (old_code, code);
312: old_codptr = codptr;
313:
314: /* save off the current namespace */
315: strncpy (old_ns, nsname, STRLEN - 1);
316:
317: nsstart = r->name + 2;
318: nssave = nsstart;
319:
320: /* grab everything between the vertical bars */
321: while ((ch = *(nsstart++)) != '|') {
322: newns[i++] = ch;
323: }
324:
325: newns[i] = '\0';
326:
327: /* load up the namespace expression into the code buffer */
328: strcpy (code, newns);
329: strcat (code, " ");
330: stcnv_c2m (code);
331:
332: /* point the code pointer at the beginning of code */
333: codptr = code;
334:
335: /* parse a string expression */
336: expr (STRING);
337:
338: /* expr (STRING) stores its result in argptr */
339: stcpy (newns, argptr);
340: stcnv_m2c (newns);
341:
342: /* restore interpreter state */
343: stcpy (code, old_code);
344: codptr = old_codptr;
345:
346: /* grab the rest of the gvn */
347: subprt = nssave + i + 1;
348: snprintf (r->name, 255, "^%s", subprt);
349:
350: /* get a fully-formed key */
351: key = mref_to_internal (r);
352:
353: /* switch to the namespace specified in the extended reference */
354: set_namespace (newns, 0);
355: if (merr () > OK) {
356:
357: if (merr () == M26) {
358: /* if namespace doesn't exist, go back to the
359: original one and raise M26 */
360: set_namespace (old_ns, 0);
361: merr_raise (M26);
362: }
363:
364: return;
365: }
366: }
367:
368: switch (r->name[1]) {
369:
370: case '%':
371: case '$':
372:
373: if ((action % 2) == 0) {
374: (*gbl_s)(get_sym, tk_buf, old_value);
375: stcpy (new_value, data);
376: merr_raise (OK);
377: }
378:
379: (*gbl_s)(action, key, data);
380: ierr_sav = ierr;
381: break;
382:
383: default:
384:
385: if ((action % 2) == 0) {
386: (*gbl_u)(get_sym, tk_buf, old_value);
387: stcpy (new_value, data);
388: merr_raise (OK);
389: }
390:
391: (*gbl_u)(action, key, data);
392: ierr_sav = ierr;
393: break;
394:
395: }
396:
397: if ((extref_flg == TRUE) || (mapped_flg == TRUE)) {
398:
399: if (mapped_flg == TRUE) {
400: strncpy (gloplib, old_gloplib, PATHLEN - 1);
401: }
402:
403: set_namespace (old_ns, 0);
404:
405: }
406:
407: if (evt_async_enabled && r->reftype == MREF_RT_GLOBAL) {
408: char an[20];
409: char ev_id[512];
410:
411: char *k_buf = (char *) malloc (STRLEN * sizeof (char));
412: char *d_buf = (char *) malloc (STRLEN * sizeof (char));
413: NULLPTRCHK(k_buf,"global");
414: NULLPTRCHK(d_buf,"global");
415:
416: mref_to_external (r, d_buf);
417: stcnv_c2m (d_buf);
418:
419: switch (action) {
420: case set_sym:
421: sprintf (an, "SET");
422: break;
423: case kill_sym:
424: case kill_all:
425: case killexcl:
426: case killone:
427: sprintf (an, "KILL");
428: break;
429: case get_sym:
430: sprintf (an, "GET");
431: break;
432: case dat:
433: sprintf (an, "DATA");
434: break;
435: case fra_order:
436: sprintf (an, "ORDER");
437: break;
438: case fra_query:
439: case bigquery:
440: sprintf (an, "QUERY");
441: break;
442: case getinc:
443: sprintf (an, "INCREMENT");
444: break;
445: case getnext:
446: sprintf (an, "NEXT");
447: break;
448: case zdata:
449: sprintf (an, "ZDATA");
450: break;
451: }
452:
453: /* NEW ^$EVENT */
454: symtab (new_sym, "^$EVENT\201", "\201");
455:
456: /* populate ^$EVENT("GLVN") with the key */
457: snprintf (k_buf, STRLEN - 1, "^$EVENT\202GLOBAL\201");
458: symtab (set_sym, k_buf, d_buf);
459:
460: if ((action % 2) == 0) {
461:
462: snprintf (k_buf, STRLEN - 1, "^$EVENT\202OLD_VALUE\201");
463: symtab (set_sym, k_buf, old_value);
464:
465: snprintf (k_buf, STRLEN - 1, "^$EVENT\202NEW_VALUE\201");
466: symtab (set_sym, k_buf, new_value);
467:
468: }
469:
470: sprintf (ev_id, "%s:%s", an, r->name);
471: evt_enqueue (ev_id, EVT_CLS_TRIGGER, 0);
472:
473: free (k_buf);
474: free (d_buf);
475: }
476:
477: free (old_value);
478: free (new_value);
479: free (r);
480: free (tk_buf);
481: free (old_ns);
482: free (mapk_buf);
483: free (mapd_buf);
484:
485: merr_raise (ierr_sav);
486:
487: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>