00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #define FREPPLE_CORE
00028 #include "frepple/model.h"
00029 #include <climits>
00030
00031
00032
00033
00034
00035
00036
00037 namespace frepple
00038 {
00039
00040
00041 DECLARE_EXPORT bool HasLevel::recomputeLevels = false;
00042 DECLARE_EXPORT bool HasLevel::computationBusy = false;
00043 DECLARE_EXPORT short unsigned HasLevel::numberOfClusters = 0;
00044 DECLARE_EXPORT short unsigned HasLevel::numberOfHangingClusters = 0;
00045
00046
00047 DECLARE_EXPORT void HasLevel::computeLevels()
00048 {
00049 computationBusy = true;
00050
00051 static Mutex levelcomputationbusy;
00052 ScopeMutexLock l(levelcomputationbusy);
00053
00054
00055
00056 while (recomputeLevels)
00057 {
00058
00059
00060
00061 recomputeLevels = false;
00062
00063
00064 for (Buffer::iterator gbuf = Buffer::begin();
00065 gbuf != Buffer::end(); ++gbuf)
00066 {
00067 gbuf->cluster = 0;
00068 gbuf->lvl = -1;
00069 }
00070 for (Resource::iterator gres = Resource::begin();
00071 gres != Resource::end(); ++gres)
00072 {
00073 gres->cluster = 0;
00074 gres->lvl = -1;
00075 }
00076 for (Operation::iterator gop = Operation::begin();
00077 gop != Operation::end(); ++gop)
00078 {
00079 gop->cluster = 0;
00080 gop->lvl = -1;
00081 }
00082
00083
00084 stack< pair<Operation*,int> > stack;
00085 Operation* cur_oper;
00086 int cur_level;
00087 Buffer *cur_buf;
00088 const Flow* cur_Flow;
00089 bool search_level;
00090 int cur_cluster;
00091 numberOfClusters = 0;
00092 numberOfHangingClusters = 0;
00093 for (Operation::iterator g = Operation::begin();
00094 g != Operation::end(); ++g)
00095 {
00096
00097 #ifdef CLUSTERDEBUG
00098 logger << "Investigating operation '" << &*g
00099 << "' - current cluster " << g->cluster << endl;
00100 #endif
00101
00102
00103 if (g->cluster)
00104 cur_cluster = g->cluster;
00105 else
00106 {
00107 cur_cluster = ++numberOfClusters;
00108 if (numberOfClusters >= USHRT_MAX)
00109 throw LogicException("Too many clusters");
00110
00111
00112 if (g->getFlows().empty() && g->getLoads().empty()
00113 && g->getSuperOperations().empty()
00114 && g->getSubOperations().empty()
00115 )
00116 {
00117 ++numberOfHangingClusters;
00118 g->lvl = 0;
00119 continue;
00120 }
00121 }
00122
00123
00124
00125
00126
00127
00128 search_level = false;
00129 if (g->getSuperOperations().empty())
00130 {
00131 search_level = true;
00132
00133 for (Operation::flowlist::const_iterator fl = g->getFlows().begin();
00134 fl != g->getFlows().end() && search_level; ++fl)
00135 if (fl->isProducer()) search_level = false;
00136 if (search_level)
00137 {
00138
00139 for (Operation::Operationlist::const_reverse_iterator
00140 i = g->getSubOperations().rbegin();
00141 i != g->getSubOperations().rend() && search_level;
00142 ++i)
00143 for (Operation::flowlist::const_iterator
00144 fl = (*i)->getFlows().begin();
00145 fl != (*i)->getFlows().end() && search_level;
00146 ++fl)
00147 if (fl->isProducer()) search_level = false;
00148 }
00149 }
00150
00151
00152 if (!search_level && g->cluster) continue;
00153
00154
00155
00156
00157
00158 stack.push(make_pair(&*g, search_level ? 0 : -1));
00159 g->cluster = cur_cluster;
00160 if (search_level) g->lvl = 0;
00161 while (!stack.empty())
00162 {
00163
00164 cur_oper = stack.top().first;
00165 cur_level = stack.top().second;
00166 stack.pop();
00167
00168 #ifdef CLUSTERDEBUG
00169 logger << " Recursing in Operation '" << *(cur_oper)
00170 << "' - current level " << cur_level << endl;
00171 #endif
00172
00173
00174 for (Operation::Operationlist::const_reverse_iterator
00175 i = cur_oper->getSubOperations().rbegin();
00176 i != cur_oper->getSubOperations().rend();
00177 ++i)
00178 {
00179 if ((*i)->lvl < cur_level)
00180 {
00181
00182 stack.push(make_pair(*i,cur_level));
00183 (*i)->lvl = cur_level;
00184 (*i)->cluster = cur_cluster;
00185 }
00186 else if (!(*i)->cluster)
00187 {
00188
00189 stack.push(make_pair(*i,-1));
00190 (*i)->cluster = cur_cluster;
00191 }
00192
00193 }
00194
00195
00196 for (Operation::Operationlist::const_reverse_iterator
00197 j = cur_oper->getSuperOperations().rbegin();
00198 j != cur_oper->getSuperOperations().rend();
00199 ++j)
00200 {
00201 if ((*j)->lvl < cur_level)
00202 {
00203
00204 stack.push(make_pair(*j,cur_level));
00205 (*j)->lvl = cur_level;
00206 (*j)->cluster = cur_cluster;
00207 }
00208 else if (!(*j)->cluster)
00209 {
00210
00211 stack.push(make_pair(*j,-1));
00212 (*j)->cluster = cur_cluster;
00213 }
00214
00215 }
00216
00217
00218 for (Operation::loadlist::const_iterator gres =
00219 cur_oper->getLoads().begin();
00220 gres != cur_oper->getLoads().end(); ++gres)
00221 {
00222 Resource *resptr = gres->getResource();
00223
00224 if (resptr->lvl < cur_level) resptr->lvl = cur_level;
00225
00226 if (!resptr->cluster)
00227 {
00228 resptr->cluster = cur_cluster;
00229
00230 for (Resource::loadlist::const_iterator resops =
00231 resptr->getLoads().begin();
00232 resops != resptr->getLoads().end(); ++resops)
00233 if (!resops->getOperation()->cluster)
00234 {
00235 stack.push(make_pair(resops->getOperation(),-1));
00236 resops->getOperation()->cluster = cur_cluster;
00237 }
00238 }
00239 }
00240
00241
00242 for (Operation::flowlist::const_iterator
00243 gflow = cur_oper->getFlows().begin();
00244 gflow != cur_oper->getFlows().end();
00245 ++gflow)
00246 {
00247 cur_Flow = &*gflow;
00248 cur_buf = cur_Flow->getBuffer();
00249
00250
00251 search_level = cur_level!=-1 && cur_buf->lvl<cur_level+1;
00252
00253
00254 if (search_level || !cur_buf->cluster)
00255 {
00256
00257 cur_buf->cluster = cur_cluster;
00258
00259
00260 for (Buffer::flowlist::const_iterator
00261 buffl = cur_buf->getFlows().begin();
00262 buffl != cur_buf->getFlows().end();
00263 ++buffl)
00264 {
00265
00266 if (cur_Flow->isConsumer() && search_level)
00267 {
00268 if (buffl->getOperation()->lvl < cur_level+1
00269 && &*buffl != cur_Flow && buffl->isProducer())
00270 {
00271 stack.push(make_pair(buffl->getOperation(),cur_level+1));
00272 buffl->getOperation()->lvl = cur_level+1;
00273 buffl->getOperation()->cluster = cur_cluster;
00274 }
00275 else if (!buffl->getOperation()->cluster)
00276 {
00277 stack.push(make_pair(buffl->getOperation(),-1));
00278 buffl->getOperation()->cluster = cur_cluster;
00279 }
00280 cur_buf->lvl = cur_level+1;
00281 }
00282
00283 else if (!buffl->getOperation()->cluster)
00284 {
00285 stack.push(make_pair(buffl->getOperation(),-1));
00286 buffl->getOperation()->cluster = cur_cluster;
00287 }
00288 }
00289 }
00290 }
00291
00292 }
00293
00294 }
00295
00296
00297
00298
00299
00300 for (Buffer::iterator gbuf2 = Buffer::begin();
00301 gbuf2 != Buffer::end(); ++gbuf2)
00302 if (gbuf2->getFlows().empty())
00303 {
00304 gbuf2->cluster = ++numberOfClusters;
00305 if (numberOfClusters >= USHRT_MAX)
00306 throw LogicException("Too many clusters");
00307 ++numberOfHangingClusters;
00308 }
00309 for (Resource::iterator gres2 = Resource::begin();
00310 gres2 != Resource::end(); ++gres2)
00311 if (gres2->getLoads().empty())
00312 {
00313 gres2->cluster = ++numberOfClusters;
00314 if (numberOfClusters >= USHRT_MAX)
00315 throw LogicException("Too many clusters");
00316 ++numberOfHangingClusters;
00317 }
00318
00319 }
00320
00321
00322
00323 computationBusy = false;
00324 }
00325
00326 }