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