|
INET Framework for OMNeT++/OMNEST
|
00001 // 00002 // Copyright (C) 2005 Andras Varga 00003 // 00004 // This program is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public License 00006 // as published by the Free Software Foundation; either version 2 00007 // of the License, or (at your option) any later version. 00008 // 00009 // This program is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU Lesser General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU Lesser General Public License 00015 // along with this program; if not, see <http://www.gnu.org/licenses/>. 00016 // 00017 00018 #include "ScenarioManager.h" 00019 00020 Define_Module(ScenarioManager); 00021 00022 00023 void ScenarioManager::initialize() 00024 { 00025 cXMLElement *script = par("script"); 00026 00027 numChanges = numDone = 0; 00028 WATCH(numChanges); 00029 WATCH(numDone); 00030 00031 for (cXMLElement *node=script->getFirstChild(); node; node = node->getNextSibling()) 00032 { 00033 // check attr t is present 00034 const char *tAttr = node->getAttribute("t"); 00035 if (!tAttr) 00036 error("attribute 't' missing at %s", node->getSourceLocation()); 00037 00038 // schedule self-message 00039 simtime_t t = STR_SIMTIME(tAttr); 00040 cMessage *msg = new cMessage("scenario-event"); 00041 msg->setContextPointer(node); 00042 scheduleAt(t, msg); 00043 00044 // count it 00045 numChanges++; 00046 } 00047 00048 updateDisplayString(); 00049 } 00050 00051 void ScenarioManager::handleMessage(cMessage *msg) 00052 { 00053 cXMLElement *node = (cXMLElement *) msg->getContextPointer(); 00054 delete msg; 00055 00056 processCommand(node); 00057 00058 numDone++; 00059 updateDisplayString(); 00060 } 00061 00062 void ScenarioManager::processCommand(cXMLElement *node) 00063 { 00064 const char *tag = node->getTagName(); 00065 EV << "processing <" << tag << "> command...\n"; 00066 00067 if (!strcmp(tag,"at")) 00068 processAtCommand(node); 00069 else if (!strcmp(tag,"set-param")) 00070 processSetParamCommand(node); 00071 else if (!strcmp(tag,"set-channel-attr")) 00072 processSetChannelAttrCommand(node); 00073 // else if (!strcmp(tag,"create-module")) 00074 // processCreateModuleCommand(node); 00075 // else if (!strcmp(tag,"connect")) 00076 // processConnectCommand(node); 00077 else 00078 processModuleSpecificCommand(node); 00079 } 00080 00081 // helper function 00082 static bool parseIndexedName(const char *s, std::string& name, int& index) 00083 { 00084 const char *b; 00085 if ((b=strchr(s,'['))==NULL || s[strlen(s)-1]!=']') 00086 { 00087 name = s; 00088 index = -1; 00089 return false; 00090 } 00091 else 00092 { 00093 name.assign(s, b-s); 00094 index = atoi(b+1); 00095 return true; 00096 } 00097 } 00098 00099 const char *ScenarioManager::getRequiredAttribute(cXMLElement *node, const char *attr) 00100 { 00101 const char *s = node->getAttribute(attr); 00102 if (!s) 00103 error("required attribute %s of <%s> missing at %s", 00104 attr, node->getTagName(), node->getSourceLocation()); 00105 return s; 00106 } 00107 00108 cModule *ScenarioManager::getRequiredModule(cXMLElement *node, const char *attr) 00109 { 00110 const char *moduleAttr = getRequiredAttribute(node, attr); 00111 cModule *mod = simulation.getModuleByPath(moduleAttr); 00112 if (!mod) 00113 error("module '%s' not found at %s", moduleAttr, node->getSourceLocation()); 00114 return mod; 00115 } 00116 00117 cGate *ScenarioManager::getRequiredGate(cXMLElement *node, const char *modAttr, const char *gateAttr) 00118 { 00119 cModule *mod = getRequiredModule(node, modAttr); 00120 const char *gateStr = getRequiredAttribute(node, gateAttr); 00121 std::string gname; 00122 int gindex; 00123 cGate *g = parseIndexedName(gateStr, gname, gindex) ? mod->gate(gname.c_str(), gindex) : mod->gate(gname.c_str()); 00124 if (!g) 00125 error("module '%s' has no gate '%s' at %s", mod->getFullPath().c_str(), gateStr, node->getSourceLocation()); 00126 return g; 00127 } 00128 00129 void ScenarioManager::processAtCommand(cXMLElement *node) 00130 { 00131 for (cXMLElement *child=node->getFirstChild(); child; child=child->getNextSibling()) 00132 processCommand(child); 00133 } 00134 00135 void ScenarioManager::processModuleSpecificCommand(cXMLElement *node) 00136 { 00137 // find which module we'll need to invoke 00138 cModule *mod = getRequiredModule(node, "module"); 00139 00140 // see if it supports the IScriptable interface 00141 IScriptable *scriptable = dynamic_cast<IScriptable *>(mod); 00142 if (!scriptable) 00143 error("<%s> not understood: it is not a built-in command of %s, and module class %s " 00144 "is not scriptable (does not subclass from IScriptable) at %s", 00145 node->getTagName(), getClassName(), mod->getClassName(), node->getSourceLocation()); 00146 00147 // ok, trust it to process this command 00148 scriptable->processCommand(*node); 00149 } 00150 00151 void ScenarioManager::processSetParamCommand(cXMLElement *node) 00152 { 00153 // process <set-param> command 00154 cModule *mod = getRequiredModule(node, "module"); 00155 const char *parAttr = getRequiredAttribute(node, "par"); 00156 const char *valueAttr = getRequiredAttribute(node, "value"); 00157 00158 EV << "Setting " << mod->getFullPath() << "." << parAttr << " = " << valueAttr << "\n"; 00159 bubble((std::string("setting: ")+mod->getFullPath()+"."+parAttr+" = "+valueAttr).c_str()); 00160 00161 // set the parameter to the given value 00162 cPar& param = mod->par(parAttr); 00163 param.parse(valueAttr); 00164 } 00165 00166 void ScenarioManager::processSetChannelAttrCommand(cXMLElement *node) 00167 { 00168 // process <set-channel-attr> command 00169 cGate *g = getRequiredGate(node, "src-module", "src-gate"); 00170 const char *attrAttr = getRequiredAttribute(node, "attr"); 00171 const char *valueAttr = getRequiredAttribute(node, "value"); 00172 00173 EV << "Setting channel attribute: " << attrAttr << " = " << valueAttr 00174 << " of gate " << g->getFullPath() << "\n"; 00175 bubble((std::string("setting channel attr: ")+attrAttr+" = "+valueAttr).c_str()); 00176 00177 // make sure gate is connected at all 00178 if (!g->getNextGate()) 00179 error("gate '%s' is not connected at %s", g->getFullPath().c_str(), node->getSourceLocation()); 00180 00181 // find channel (or add one?) 00182 cChannel *chan = g->getChannel(); 00183 if (!chan) 00184 error("connection starting at gate '%s' has no attributes at %s", g->getFullPath().c_str(), node->getSourceLocation()); 00185 00186 // set the parameter to the given value 00187 if (!chan->hasPar(attrAttr)) 00188 ; //FIXME remove this "if" 00189 cPar& param = chan->par(attrAttr); 00190 param.parse(valueAttr); 00191 } 00192 00193 void ScenarioManager::processCreateModuleCommand(cXMLElement *node) 00194 { 00195 // FIXME finish and test 00196 } 00197 00198 void ScenarioManager::processDeleteModuleCommand(cXMLElement *node) 00199 { 00200 // FIXME finish and test 00201 } 00202 00203 void ScenarioManager::processConnectCommand(cXMLElement *node) 00204 { 00205 // FIXME finish and test 00206 } 00207 00208 void ScenarioManager::processDisconnectCommand(cXMLElement *node) 00209 { 00210 // FIXME finish and test 00211 } 00212 00213 void ScenarioManager::updateDisplayString() 00214 { 00215 char buf[80]; 00216 sprintf(buf, "total %d changes, %d left", numChanges, numChanges-numDone); 00217 getDisplayString().setTagArg("t", 0, buf); 00218 } 00219