📄 mal_scenario.mx
字号:
for (i = 0; i < MAXSCEN && scen->name; i++, scen++) if (strcmp(scen->name, nme) == 0) return scen; return NULL;}@-Functions may become resolved only after the corresponding modulehas been loaded. This should be announced as part of the moduleprelude code.Beware that after the update, we also have to adjust the client records.They contain a copy of the functions addresses.@= updLineif( scen->@1 && strcmp(scen->@1,nme) == 0){ Client c1; scen->@1Cmd = fcn; for(c1 = mal_clients; c1 < mal_clients+MAL_MAXCLIENTS; c1++) if(@2 && c1->scenario && strcmp(c1->scenario,scen->name)==0) c1->phase[@2]= fcn; else if(@2 && c1->oldscenario && strcmp(c1->oldscenario,scen->name)==0) c1->oldphase[@2]= fcn;}@cvoidupdateScenario(str nme, MALfcn fcn){ int i; Scenario scen = scenarioRec; for (i = 0; i < MAXSCEN && scen->name; i++, scen++) { @:updLine(initSystem, 0)@ @:updLine(exitSystem, 0)@ @:updLine(initClient, INITCLIENT)@ @:updLine(exitClient, EXITCLIENT)@ @:updLine(reader, READER)@ @:updLine(parser, PARSER)@ @:updLine(optimizer, OPTIMIZE)@ @:updLine(tactics, SCHEDULER)@ @:updLine(engine, ENGINE)@ }}voidshowScenarioByName(stream *f, str nme){ Scenario scen = findScenario(nme); if (scen) showScenario(f, scen);}voidshowAllScenarios(stream *f){ int i; Scenario scen = scenarioRec; for (i = 0; i < MAXSCEN && scen->name; i++, scen++) showScenario(f, scen);}str getScenarioLanguage(Client c){ Scenario scen= findScenario(c->scenario); if( scen) return scen->language; return "mal";}@-Changing the scenario for a particular client invalidates thestate maintained for the previous scenario. The old scenario isretained in the client record to facilitate propagation of state information, or to simply switch back to the previous one.Before we initialize a scenario the client scenario is reset tothe MAL scenario. This implies that all scenarios are initializedusing the same scenario. After the scenario initialization file has been processed, the scenario phases are replaced with theproper ones.@-All client records should be initialized with a defaultscenario, i.e. the first described in the scenario table.@cstrfillScenario(Client c, Scenario scen){ c->scenario = scen->name; c->phase[READER] = scen->readerCmd; c->phase[PARSER] = scen->parserCmd; c->phase[OPTIMIZE] = scen->optimizerCmd; c->phase[SCHEDULER] = scen->tacticsCmd; c->phase[ENGINE] = scen->engineCmd; c->phase[INITCLIENT] = scen->initClientCmd; c->phase[EXITCLIENT] = scen->exitClientCmd; c->state[READER] = 0; c->state[PARSER] = 0; c->state[OPTIMIZE] = 0; c->state[SCHEDULER] = 0; c->state[ENGINE] = 0; c->state[INITCLIENT] = 0; c->state[EXITCLIENT] = 0; if (scen->initClientCmd) return((*scen->initClientCmd) (c)); return(MAL_SUCCEED);}voidclrScenario(Client c){ if (c->scenario == 0) return; c->scenario = 0; c->phase[READER] = 0; c->phase[PARSER] = 0; c->phase[OPTIMIZE] = 0; c->phase[SCHEDULER] = 0; c->phase[ENGINE] = 0; c->phase[INITCLIENT] = 0; c->phase[EXITCLIENT] = 0; c->state[READER] = 0; c->state[PARSER] = 0; c->state[OPTIMIZE] = 0; c->state[SCHEDULER] = 0; c->state[ENGINE] = 0; c->state[INITCLIENT] = 0; c->state[EXITCLIENT] = 0;}@-Setting a new scenario calls for saving the previous stateand execution of the initClientScenario routine.@cstrsetScenario(Client c, str nme){ int i; str msg; Scenario scen = scenarioRec; scen = findScenario(nme); if (scen == NULL) throw(MAL, "setScenario", "Scenario '%s' not initialized", nme); if (c->scenario) { c->oldscenario = c->scenario; for (i = 0; i < 7; i++) { c->oldstate[i] = c->state[i]; c->oldphase[i] = c->phase[i]; } } for (i = 0; i < 7; i++) c->state[i] = 0; msg = initScenario(c, scen); if (msg) return msg; return MAL_SUCCEED;}@-After finishing a session in a scenario, we should reset thestate of the previous one. But also call the exitClientto garbage collect any scenario specific structures.@cstrgetCurrentScenario(Client c){ return c->scenario;}voidresetScenario(Client c){ int i; Scenario scen = scenarioRec; if (c->scenario == 0) return; scen = findScenario(c->scenario); if (scen != NULL && scen->exitClientCmd) (*scen->exitClientCmd) (c); c->scenario = c->oldscenario; for (i = 0; i < 7; i++) { c->state[i] = c->oldstate[i]; c->phase[i] = c->oldphase[i]; } c->oldscenario = 0;}voidexitScenario(Client c){ Scenario scen = scenarioRec; if (c->scenario == 0) return; scen = findScenario(c->scenario); if (scen->exitSystemCmd) (*scen->exitSystemCmd) (c);}@}@- The building blocks of scenarios are routines obeying a strictname signature. They require exclusive access to the clientrecord. Any specific information should be accessible fromthere, e.g. access to a scenario specific state descriptor.The client scenario initialization and finalization bracketsare @sc{xyzinitClient()} and @sc{xyzexitClient()}.The @sc{xyzparser(Client c)} contains the parser for language XYZand should fill the MAL program block associated with the client record.The latter may have been initialized with variables. Each language parser may require a catalog with informationon the translation of language specific datastructures into their BATequivalent.The @sc{xyzoptimizer(Client c)} contains language specific optimizationsusing the MAL intermediate code as a starting point.The @sc{xyztactics(Client c)} synchronizes the program execution with thestate of the machine, e.g. claiming resources, the history of the client or alignment of the request with concurrent actions (e.g. transactioncoordination).The @sc{xyzengine(Client c)} contains the applicable back-end engine.The default is the MAL interpreter, which provides good balancebetween speed and ability to analysis its behavior.@-@{@= runPhase if(msg== MAL_SUCCEED && c->phase[@1] && ((msg= (str) (*c->phase[@1])(c)) || c->mode <= FINISHING)){ /* error occurred */#ifdef MAL_SCENARIO_DEBUG stream_printf(GDKstdout,"Error in @1 phase\n"); if( /*c->mode > FINISHING &&*/ msg ) stream_printf(GDKstdout,"%s",msg);#endif if (msg) { /* FIXME: why is the error not handed back to the user here? */ GDKfree(msg); msg=0; } continue; }@-Access control enforcement. Except for the server ownerrunning a scenario should be explicitly permitted.@cstrrunScenarioBody(Client c){ str msg= MAL_SUCCEED;/* postponed if( !isServerOwner(c) ){ c->mode = FINISHING; }*/ while (c->mode > FINISHING) { msg = MAL_SUCCEED; @:runPhase(READER)@ @:runPhase(PARSER)@ @:runPhase(OPTIMIZE)@ @:runPhase(SCHEDULER)@ @:runPhase(ENGINE)@ } return msg;}strrunScenario(Client c){ int cnt = 0; str msg = MAL_SUCCEED; Client c1; if( c== 0 || c->phase[READER] == 0) return msg; msg= runScenarioBody(c); if( msg != MAL_SUCCEED) stream_printf(c->fdout,"!%s\n",msg);#ifdef MAL_SCENARIO_DEBUG printf("About to terminate scenario %s\n", c->scenario);#endif@-Check if we are closing the last client, because then we alsohave to call the scenario exit.@c if( c->scenario) for (c1 = mal_clients; c1 < mal_clients + MAL_MAXCLIENTS; c1++) if (c1->scenario && strcmp(c->scenario, c1->scenario) == 0) cnt++; if (c->phase[EXITCLIENT]) {#ifdef MAL_SCENARIO_DEBUG printf("Calling client exit function \n");#endif (*c->phase[EXITCLIENT]) (c); }#ifdef MAL_SCENARIO_DEBUG printf("scenario client cnt %d\n",cnt);#endif if (cnt == 1) { exitScenario(c); } return msg;}@-@}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -