src/Sim/Foundation/Resource/Builder/ResourceBuilder.cpp

説明を見る。
00001 // 
00002 // Copyright (c) 2005-2008 Kenichi Watanabe.
00003 // Copyright (c) 2005-2008 Yasuhiro Watari.
00004 // Copyright (c) 2005-2008 Hironori Ichibayashi.
00005 // Copyright (c) 2008-2009 Kazuo Horio.
00006 // Copyright (c) 2009-2013 Naruki Kurata.
00007 // Copyright (c) 2005-2013 Ryota Shioya.
00008 // Copyright (c) 2005-2013 Masahiro Goshima.
00009 // 
00010 // This software is provided 'as-is', without any express or implied
00011 // warranty. In no event will the authors be held liable for any damages
00012 // arising from the use of this software.
00013 // 
00014 // Permission is granted to anyone to use this software for any purpose,
00015 // including commercial applications, and to alter it and redistribute it
00016 // freely, subject to the following restrictions:
00017 // 
00018 // 1. The origin of this software must not be misrepresented; you must not
00019 // claim that you wrote the original software. If you use this software
00020 // in a product, an acknowledgment in the product documentation would be
00021 // appreciated but is not required.
00022 // 
00023 // 2. Altered source versions must be plainly marked as such, and must not be
00024 // misrepresented as being the original software.
00025 // 
00026 // 3. This notice may not be removed or altered from any source
00027 // distribution.
00028 // 
00029 // 
00030 
00031 
00032 //
00033 // The factory class for physical resources
00034 //
00035 
00036 #include <pch.h>
00037 #include "Sim/Foundation/Resource/Builder/ResourceBuilder.h"
00038 
00039 using namespace std;
00040 using namespace boost;
00041 using namespace Onikiri;
00042 
00043 static int INVALID_NODE_COUNT = -1;
00044 static int INVALID_NODE_CLUSTER = -1;
00045 
00046 static const char g_configNamePath[] = "/Session/Simulator/@Configuration";
00047 static const char g_configRootPath[] = "/Session/Simulator/Configurations/";
00048 static const char g_resultRootPath[] = "/Session/Result/Resource/";
00049 
00050 ResourceBuilder::ResNode::ResNode()
00051 {
00052     count = INVALID_NODE_COUNT;
00053     cluster = INVALID_NODE_CLUSTER;
00054     copyCount = INVALID_NODE_COUNT;
00055     external = false;
00056 }
00057 
00058 ResourceBuilder::ResourceBuilder()
00059 {
00060     m_rootNode = ResNodePtr( new ResNode() );
00061 }
00062 
00063 ResourceBuilder::~ResourceBuilder()
00064 {
00065     Release();
00066 }
00067 
00068 // Release all configuration data
00069 void ResourceBuilder::Release()
00070 {
00071     for( size_t i = 0; i < m_instanceList.size(); i++ ){
00072         m_instanceList[i]->Finalize();
00073     }
00074 
00075     m_rootNode->children.clear();
00076     m_constMap.clear();
00077 
00078     for( size_t i = 0; i < m_instanceList.size(); i++ ){
00079         delete m_instanceList[i];
00080     }
00081     m_instanceList.clear();
00082 }
00083 
00084 ParamXMLPath ResourceBuilder::GetConfigurationPath()
00085 {
00086     // Get configuration name
00087     ParamXMLPath cfgNamePath = g_configNamePath;
00088     String cfgName;
00089     g_paramDB.Get( cfgNamePath, &cfgName );
00090 
00091     // Get configuration count
00092     ParamXMLPath cfgPath = g_configRootPath + cfgName;
00093 
00094     XMLNodeArray* copyNodes = 
00095         g_paramDB.GetXMLTree().GetNodeArray( cfgPath );
00096 
00097     if( copyNodes == NULL ){
00098         THROW_RUNTIME_ERROR(
00099             "The specified configuration '%s' (%s) is not found.",
00100             cfgName.c_str(),
00101             cfgPath.ToString().c_str()
00102         );
00103     }
00104 
00105 
00106     return cfgPath;
00107 }
00108 
00109 // Load the constant section in the parameter XML
00110 void ResourceBuilder::LoadConstantSection( const ParamXMLPath& rootPath )
00111 {
00112     ParamXMLPath constPath = rootPath + "Constant";
00113     ParamXMLTree& tree = g_paramDB.GetXMLTree();
00114 
00115     XMLNodePtr constantNode = 
00116         tree.GetNode( constPath );
00117     
00118     if( constantNode == NULL ){
00119         return;
00120     }
00121 
00122     XMLAttributeMap& attributes = 
00123         constantNode->attributes;
00124 
00125     for( XMLAttributeMap::iterator i = attributes.begin();
00126          i != attributes.end();
00127          ++i
00128      ){
00129          m_constMap[i->first] = 
00130              lexical_cast<int>( i->second->value );
00131          i->second->accessed = true;
00132     }
00133 
00134 }
00135 
00136 // Load the parameter section in the parameter XML.
00137 // This method loads the path of the node and save it in the node map.
00138 // The parameter value is loaded in a object inherited from the ParamExchange 
00139 // with this saved path.
00140 void ResourceBuilder::LoadParameterSection( const ParamXMLPath& rootPath )
00141 {
00142     ParamXMLPath parameterBasePath = rootPath + "Parameter";
00143 
00144     ParamXMLTree& tree = 
00145         g_paramDB.GetXMLTree();
00146 
00147     XMLNodePtr xmlParent = tree.GetNode( parameterBasePath );
00148     if( xmlParent == NULL ){
00149         return;
00150     }
00151 
00152     for( XMLChildMap::iterator children = xmlParent->children.begin();
00153          children != xmlParent->children.end();
00154          ++children
00155     ){
00156         for( size_t childIndex = 0; childIndex < children->second.size(); childIndex++ ){
00157             XMLNodePtr xmlNode = children->second[childIndex];
00158 
00159             ParamXMLPath paramPath = parameterBasePath;
00160             paramPath.AddArray( xmlNode->name, (int)childIndex );
00161             const ParamXMLPath& namePath  = paramPath + "@Name";
00162             
00163             //const String& key = element;
00164             String name;
00165             bool hit = g_paramDB.Get( namePath.ToString(), &name, false );
00166             if( !hit ){
00167                 THROW_RUNTIME_ERROR( 
00168                     "'%s' does not have 'Name' attribute.\n"
00169                     "A node in a 'Parameter' section must have 'Name' attribute.",
00170                     paramPath.ToString().c_str() 
00171                 );
00172             }
00173 
00174             ResNodeMap::iterator entry = m_resNodeMap.find( name );
00175             if( entry == m_resNodeMap.end() ){
00176                 THROW_RUNTIME_ERROR(
00177                     "The node of the name '%s' is not found in the 'Structure' section.\n"
00178                     "All nodes in a 'Parameter' section must be defined in a 'Structure' section.\n"
00179                     "path: %s",
00180                     name.c_str(),
00181                     paramPath.ToString().c_str() 
00182                 );
00183             }
00184 
00185             entry->second->paramPath = paramPath.ToString();
00186 
00187             // Make result path
00188             ParamXMLPath resultPath = g_resultRootPath;
00189             resultPath.AddArray( xmlNode->name, (int)childIndex );
00190             entry->second->resultPath = resultPath.ToString();
00191         }
00192     }
00193 }
00194 
00195 
00196 //
00197 // Get attribute of 'Structure' node 
00198 //
00199 
00200 
00201 int ResourceBuilder::GetStructureNodeValue(
00202     const XMLNodePtr node, const String& attrName )
00203 {
00204     XMLAttributeMap::iterator attr = node->attributes.find( attrName );
00205     if( attr == node->attributes.end() ){
00206         return INVALID_NODE_COUNT;
00207     }
00208 
00209     const String& valueStr = attr->second->value;
00210     attr->second->accessed = true;
00211 
00212     map<String, int>::iterator i = m_constMap.find( valueStr );
00213     if( i != m_constMap.end() ){
00214         return i->second;
00215     }
00216     else{
00217         return lexical_cast<int>( valueStr );
00218     }
00219 }
00220 
00221 String ResourceBuilder::GetStructureNodeString(
00222     const XMLNodePtr node, const String& attrName )
00223 {
00224     XMLAttributeMap::iterator attr = node->attributes.find( attrName );
00225     if( attr != node->attributes.end() ){
00226         attr->second->accessed = true;
00227         return attr->second->value;
00228     }
00229     else{
00230         return "";
00231     }
00232 }
00233 
00234 //
00235 // --- Load the structure section
00236 //
00237 
00238 // Process structure nodes recursively
00239 void ResourceBuilder::TraverseStructureNode(ResNodePtr resParent, XMLNodePtr xmlParent, int copyCount)
00240 {
00241     for( XMLChildMap::iterator children = xmlParent->children.begin();
00242          children != xmlParent->children.end();
00243          ++children
00244     ){
00245         for( size_t childIndex = 0; childIndex < children->second.size(); childIndex++ ){
00246             XMLNodePtr xmlNode = children->second[childIndex];
00247             ResNodePtr resNode( new ResNode );
00248 
00249             const String& type = xmlNode->name;
00250 
00251             if( type == "Connection" ){
00252                 // Connection node
00253                 ResNode::Child child;
00254                 child.name = GetStructureNodeString( xmlNode, "Name" );
00255                 child.to   = GetStructureNodeString( xmlNode, "To" );
00256                 resParent->children.push_back( child );
00257             }
00258             else{
00259                 // General node
00260                 resNode->type    = type;
00261                 resNode->name    = GetStructureNodeString( xmlNode, "Name" );
00262                 resNode->count   = GetStructureNodeValue( xmlNode, "Count" );
00263                 resNode->cluster = GetStructureNodeValue( xmlNode, "Cluster" );
00264 
00265                 if( resNode->count != INVALID_NODE_COUNT){
00266                     resNode->copyCount = copyCount;
00267                 }
00268 
00269                 //printf("type:%s\tname:%s\tcount:%d\n", node->type.c_str(), node->name.c_str(), node->count);
00270 
00271                 String connectionTo = GetStructureNodeString( xmlNode, "To" );
00272 
00273                 ResNodeMap::iterator entry = m_resNodeMap.find( resNode->name );
00274                 if(entry != m_resNodeMap.end()){
00275                     // Update a existent node int the 'm_resNodeMap'
00276                     ResNodePtr entryPtr = entry->second;
00277                     
00278                     ResNode::Child child;
00279                     child.node = entryPtr;
00280                     child.to   = connectionTo;
00281                     resParent->children.push_back( child );
00282 
00283                     if( entryPtr->type != resNode->type ){
00284                         THROW_RUNTIME_ERROR(
00285                             "The node '%s' is re-defined by the different type '%s' in the 'Structure' section.\n"
00286                             "The original type of the node is '%s'.",
00287                             resNode->name.c_str(),
00288                             resNode->type.c_str(),
00289                             entryPtr->type.c_str()
00290                         );
00291                     }
00292 
00293                     if( entryPtr->count != resNode->count && 
00294                         entryPtr->count != INVALID_NODE_COUNT &&
00295                         resNode->count  != INVALID_NODE_COUNT 
00296                     ){
00297                         THROW_RUNTIME_ERROR(
00298                             "The count of '%s' is re-defined in 'Structure' section.",
00299                             resNode->name.c_str()
00300                         );
00301                     }
00302 
00303                     if( entryPtr->copyCount != resNode->copyCount && 
00304                         entryPtr->copyCount != INVALID_NODE_COUNT &&
00305                         resNode->copyCount != INVALID_NODE_COUNT 
00306                     ){
00307                         THROW_RUNTIME_ERROR(
00308                             "The copy count of '%s' is re-defined in 'Structure' section.",
00309                             resNode->name.c_str()
00310                         );
00311                     }
00312 
00313                     if( entryPtr->cluster != resNode->cluster && entryPtr->cluster != INVALID_NODE_CLUSTER ){
00314                         THROW_RUNTIME_ERROR(
00315                             "The cluster of '%s' is re-defined in 'Structure' section.",
00316                             resNode->name.c_str()
00317                         );
00318                     }
00319 
00320                     if( resNode->count != INVALID_NODE_COUNT ){
00321                         entryPtr->count = resNode->count;
00322                     }
00323 
00324                     if( resNode->copyCount != INVALID_NODE_COUNT ){
00325                         entryPtr->copyCount = resNode->copyCount;
00326                     }
00327 
00328                     if( resNode->cluster != INVALID_NODE_CLUSTER ){
00329                         entryPtr->cluster = resNode->cluster;
00330                     }
00331 
00332                     resNode = entryPtr;
00333                 }
00334                 else{   // if(entry != m_resNodeMap.end()){
00335                     
00336                     // Add a new node to the 'm_resNodeMap'
00337                     m_resNodeMap[resNode->name] = resNode;
00338 
00339                     ResNode::Child child;
00340                     child.node = resNode;
00341                     child.to   = connectionTo;
00342                     resParent->children.push_back( child );
00343                 }
00344             }
00345 
00346             TraverseStructureNode( resNode, xmlNode, copyCount );
00347         }
00348     }
00349 }
00350 
00351 
00352 // Process structure nodes recursively
00353 void ResourceBuilder::LoadStructureSection(const ParamXMLPath& structPath)
00354 {
00355     const ParamXMLPath& copyPath = structPath + "/Structure/Copy";
00356 
00357     ParamXMLTree& tree = 
00358         g_paramDB.GetXMLTree();
00359     
00360     XMLNodeArray* copyNodes = 
00361         tree.GetNodeArray( copyPath );
00362 
00363     if( !copyNodes ){
00364         THROW_RUNTIME_ERROR(
00365             "The 'Structure' node '%s' does not have any copy node.",
00366             (structPath + "Structure").ToString().c_str()
00367         );
00368     }
00369 
00370     for( size_t i = 0; i < copyNodes->size(); i++ ){
00371 
00372         XMLNodePtr copyNode = copyNodes->at(i);
00373         int copyCount = GetStructureNodeValue( copyNode, "Count" );
00374 
00375         if( copyCount == INVALID_NODE_COUNT ){
00376             THROW_RUNTIME_ERROR( 
00377                 "The 'Copy' node ('%s') does not have a 'Count' attribute.",
00378                 copyPath.ToString().c_str()
00379             );
00380         }
00381 
00382         TraverseStructureNode( m_rootNode, copyNode, copyCount );
00383     }
00384 }
00385 
00386 
00387 // Construct each resource from the loaded node map
00388 void ResourceBuilder::ConstructResources()
00389 {
00390     vector<int> tidList;
00391     vector<int> pidList;
00392 
00393     for( ResNodeMap::iterator i = m_resNodeMap.begin();
00394          i != m_resNodeMap.end();
00395          ++i
00396     ){
00397         ResNodePtr node = i->second;
00398         int count = node->count;
00399 
00400         if( node->external )
00401             continue;
00402 
00403         for( int rid = 0; rid < count; rid++ ){
00404             // Create an instance of the resource
00405             PhysicalResourceNode* res = 
00406                 m_factory.CreateInstance( node->type );
00407             PhysicalResourceNodeInfo info;
00408 
00409             info.name = node->name;
00410             info.typeName = node->type;
00411             info.paramPath = node->paramPath;
00412             info.resultRootPath = node->resultPath;
00413             info.resultPath.SetArray( node->resultPath, "Result", rid );
00414 
00415             if( info.paramPath.ToString() == "" ){
00416                 THROW_RUNTIME_ERROR(
00417                     "The node '%s' does not have its parameter node in the parameter XML.\n"
00418                     "A node in the 'Structure' section must have its parameter node "
00419                     "in the 'Parameter' section.",
00420                     info.name.c_str()
00421                 );
00422             }
00423 
00424             res->SetInfo( info );
00425             res->SetRID( rid );
00426 
00427             node->instances.push_back( res );
00428             m_instanceList.push_back( res );
00429 
00430             // Set TID
00431             // The count of 'Copy' is equal to the maximum count in the resources. 
00432             // Usually, 'Copy' is equal to the count of 'Thread'.
00433             int copyCount = node->copyCount;
00434             if( copyCount < count ){
00435                 THROW_RUNTIME_ERROR( 
00436                     "The resource count  is greater than the copy count.\n"
00437                     "Node:%s Copy Count:%d  Resouce Count:%d",
00438                     info.name.c_str(),
00439                     copyCount,
00440                     count
00441                 );
00442             }
00443             if( copyCount % count != 0 ){
00444                 THROW_RUNTIME_ERROR( 
00445                     "The copy count is not divided by the resource count.\n"
00446                     "Copy Count:%d  Resouce Count:%d",
00447                     info.name.c_str(),
00448                     copyCount,
00449                     count
00450                 );
00451             }
00452             int tidCount = copyCount / count;
00453             res->SetThreadCount( tidCount );
00454             for( int i = 0; i < tidCount; i++ ){
00455                 res->SetTID( i, rid*tidCount+i );
00456             }
00457 
00458 #if 0
00459             // Set TID
00460             CalculateID( tidList, rid, node->copyCount, node, CALC_ID_THREAD );
00461             res->SetThreadCount( tidList.size() );
00462             for( size_t i = 0; i < tidList.size(); i++ ){
00463                 res->SetTID( i, tidList[i] );
00464             }
00465 
00466             // Set PID
00467             CalculateID( pidList, rid, m_processCount, node, CALC_ID_PROCESS );
00468             res->SetProcessCount( pidList.size() );
00469             for( size_t i = 0; i < pidList.size(); i++ ){
00470                 res->SetPID( i, pidList[i] );
00471             }
00472 #endif
00473         }
00474     }
00475 }
00476 
00477 // Connect each resource
00478 void ResourceBuilder::ConnectResources()
00479 {
00480     PhysicalResourceArray< PhysicalResourceNode > arrayArg;
00481 
00482     for( ResNodeMap::iterator i = m_resNodeMap.begin();
00483          i != m_resNodeMap.end();
00484          ++i
00485     ){
00486         vector< ResNode::Child >& children = i->second->children;
00487         vector< PhysicalResourceNode* >& instances = i->second->instances;
00488 
00489         for( vector< ResNode::Child >::iterator child = children.begin();
00490              child != children.end();
00491              ++child
00492         ){
00493 
00494             ResNodePtr childNode;
00495             if( child->node != NULL ){
00496                 // The child is specified by the pointer.
00497                 childNode = child->node;
00498             }
00499             else{
00500                 // The child is specified by the name.
00501                 ResNodeMap::iterator childNodeIterator =
00502                     m_resNodeMap.find( child->name );
00503                 if( childNodeIterator == m_resNodeMap.end() ){
00504                     THROW_RUNTIME_ERROR(
00505                         "The node '%s' is not defined. "
00506                         "This node is in the '%s'.", 
00507                         child->name.c_str(),
00508                         i->second->name.c_str()
00509                     );
00510                 }
00511                 childNode = childNodeIterator->second;
00512             }
00513 
00514             vector< PhysicalResourceNode* >&
00515                 childInstances = childNode->instances;
00516 
00517             if( instances.size() < childInstances.size() ){
00518                 // A case that the number of the parents is smaller than that of children.
00519                 ASSERT( childInstances.size() % instances.size() == 0 );
00520                 for( size_t i = 0; i < instances.size(); i++ ){
00521                     
00522                     size_t childrenCount = childInstances.size() / instances.size();
00523                     arrayArg.Resize( (int)childrenCount );
00524                     for( size_t c = 0; c < childrenCount; c++ ){
00525                         arrayArg[(int)c] = childInstances[ i*childrenCount + c ];
00526                     }
00527                     instances[i]->ConnectResource( arrayArg, childNode->name, child->to, false );
00528                 }
00529             }
00530             else{
00531                 // A case that the number of the parents is equal or greater than that of children.
00532                 // In this case, one child is shared by the multiple parents.
00533                 ASSERT( instances.size() % childInstances.size() == 0 );
00534                 for( size_t i = 0; i < instances.size(); i++ ){
00535                     arrayArg.Resize( 1 );
00536                     size_t childIndex = i*childInstances.size()/instances.size();
00537                     arrayArg[0] = childInstances[ childIndex ];
00538                     instances[i]->ConnectResource( arrayArg, childNode->name, child->to, false );
00539                 }
00540             }
00541         }
00542 
00543     }
00544 }
00545 
00546 // Initialize all nodes
00547 void ResourceBuilder::InitializeNodes( PhysicalResourceNode::InitPhase phase )
00548 {
00549     for( ResNodeMap::iterator i = m_resNodeMap.begin();
00550          i != m_resNodeMap.end();
00551          ++i
00552     ){
00553         ResNodePtr node = i->second;
00554         for( int rid = 0; rid < node->count; rid++ ){
00555             node->instances[rid]->Initialize( phase );
00556         }
00557     }
00558 }
00559 
00560 // Validate connection.
00561 void ResourceBuilder::ValidateConnection()
00562 {
00563     for( ResNodeMap::iterator i = m_resNodeMap.begin();
00564          i != m_resNodeMap.end();
00565          ++i
00566     ){
00567         ResNodePtr node = i->second;
00568         for( int rid = 0; rid < node->count; rid++ ){
00569             node->instances[rid]->ValidateConnection();
00570         }
00571     }
00572 }
00573 
00574 // Set external resource
00575 void ResourceBuilder::SetExternalResource( ResNode* node )
00576 {
00577     ResNodePtr nodePtr = ResNodePtr( new ResNode() );
00578     *nodePtr = *node;
00579     nodePtr->external = true;
00580     m_resNodeMap[node->name] = nodePtr;
00581 }
00582 
00583 //
00584 // --- Construct all physical resources
00585 //
00586 void ResourceBuilder::Construct()
00587 {
00588     const ParamXMLPath& cfgPath = GetConfigurationPath();
00589 
00590     LoadConstantSection( cfgPath );
00591     LoadStructureSection( cfgPath );
00592     LoadParameterSection( cfgPath );
00593 
00594     //Dump();
00595 
00596     ConstructResources();
00597     InitializeNodes( PhysicalResourceNode::INIT_PRE_CONNECTION );
00598     ConnectResources();
00599     ValidateConnection();
00600     InitializeNodes( PhysicalResourceNode::INIT_POST_CONNECTION );
00601 
00602 }
00603 
00604 // --- Dump the loaded data for debug
00605 void ResourceBuilder::Dump()
00606 {
00607     printf("--- ResNode connection : \n");
00608     for( ResNodeMap::iterator i = m_resNodeMap.begin();
00609          i != m_resNodeMap.end();
00610          ++i
00611     ){
00612         printf( 
00613             "%s : %s : %d\n", 
00614             i->second->type.c_str(),
00615             i->second->name.c_str(),
00616             i->second->count 
00617         );
00618 
00619         for( size_t j = 0; j < i->second->children.size(); j++ ){
00620             ResNode::Child child = i->second->children[j];
00621             if( child.node != NULL ){
00622                 ResNodePtr ptr = child.node;
00623                 printf( 
00624                     "  %s : %s : %d\n", 
00625                     ptr->type.c_str(),
00626                     ptr->name.c_str(),
00627                     ptr->count 
00628                 );
00629             }
00630             else{
00631                 printf( 
00632                     "  Connection : %s : %s\n", 
00633                     child.name.c_str(),
00634                     child.to.c_str()
00635                 );
00636             }
00637         }
00638     }
00639 
00640     printf("\n--- Constant list : \n");
00641     for( ConstantMap::iterator i = m_constMap.begin();
00642          i != m_constMap.end();
00643          ++i 
00644      ){
00645          printf( "%s : %d\n", i->first.c_str(), i->second );
00646     }
00647 
00648     printf("\n--- ResNode list : \n");
00649     for( ResNodeMap::iterator i = m_resNodeMap.begin();
00650          i != m_resNodeMap.end();
00651          ++i
00652     ){
00653         for( size_t j = 0; j < i->second->instances.size(); j++ ){
00654             PhysicalResourceNode* res = i->second->instances[j];
00655             printf( "%s tid(", i->second->name.c_str() );
00656             for( int ti = 0; ti < res->GetThreadCount(); ti++ ){
00657                 printf( "%d", res->GetTID( ti ) );
00658                 if( ti + 1 < res->GetThreadCount() )
00659                     printf(",");
00660             }
00661             printf( ")\n" );
00662 /*          printf( ") pid(" );
00663             for( int pi = 0; pi < res->GetProcessCount(); pi++ ){
00664                 printf( "%d", res->GetPID( pi ) );
00665                 if( pi + 1 < res->GetProcessCount() )
00666                     printf(",");
00667             }
00668             printf( ")\n" );
00669 */      }
00670     }
00671 }
00672 
00673 

Onikiri2に対してTue Jun 18 14:34:23 2013に生成されました。  doxygen 1.4.7