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>