Go to the documentation of this file.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 #ifndef GLITE_WMS_COMMON_REQUESTAD_DAGAD_H
00027 #define GLITE_WMS_COMMON_REQUESTAD_DAGAD_H
00028
00029 #include <string>
00030 #include <utility>
00031 #include <map>
00032 #include <set>
00033 #include <iosfwd>
00034 #include <classad_distribution.h>
00035 #include <exception>
00036
00037 #include <boost/shared_ptr.hpp>
00038 #include <boost/utility.hpp>
00039 #include <boost/tuple/tuple.hpp>
00040 #include <boost/config.hpp>
00041
00042 #include "glite/wmsutils/classads/classad_utils.h"
00043
00044
00045 #include <boost/graph/adjacency_list.hpp>
00046 #include <boost/graph/graph_traits.hpp>
00047 #include <boost/graph/depth_first_search.hpp>
00048 #include <boost/graph/visitors.hpp>
00049
00050 namespace glite {
00051 namespace jdl {
00052
00053 namespace utilities = glite::wmsutils::classads;
00054
00055 class DAG_Error: public std::exception
00056 {
00057 protected:
00058 std::string m_msg;
00059 public:
00060 virtual char const* what() const throw() { return "Invalid DAG"; }
00061 virtual ~DAG_Error() throw() { };
00062 };
00063
00064 class NotDAG: public DAG_Error
00065 {
00066 public:
00067 virtual char const* what() const throw() {
00068 return "'node_type' must be \"dag\"";
00069 }
00070 };
00071
00072 class InvalidMaxRunningNodes: public DAG_Error
00073 {
00074 public:
00075 virtual char const* what() const throw() {
00076 return "'max_running_nodes' has to be an integer > 0";
00077 }
00078 };
00079
00080 class InvalidNodes: public DAG_Error
00081 {
00082 public:
00083 virtual char const* what() const throw() {
00084 return "'nodes' not valid";
00085 }
00086 };
00087
00088 class InvalidDependencies: public DAG_Error
00089 {
00090 public:
00091 virtual char const* what() const throw() {
00092 return "'dependencies' not valid";
00093 }
00094 };
00095
00096 class InconsistentDependencies: public DAG_Error
00097 {
00098 public:
00099 virtual char const* what() const throw() {
00100 return "Invalid reference in 'dependencies'";
00101 }
00102 };
00103
00104 class DAG_HasCycle: public DAG_Error
00105 {
00106 public:
00107 virtual char const* what() const throw() {
00108 return "DAG has a cycle";
00109 }
00110 };
00111
00112 class Invalid_DAG_NodeType: public DAG_Error
00113 {
00114 private:
00115 std::string m_type;
00116 public:
00117 Invalid_DAG_NodeType(std::string const& type)
00118 : DAG_Error(), m_type(type)
00119 { }
00120 virtual char const* what() throw() {
00121 m_msg = "'node_type': " + m_type + " is not valid";
00122 return m_msg.c_str();
00123 }
00124 virtual ~Invalid_DAG_NodeType() throw() { }
00125 };
00126
00127 class Invalid_DAG_RetryCount: public DAG_Error
00128 {
00129 public:
00130 virtual char const* what() const throw() {
00131 return "'node_retry_count' must be an integer >= 0";
00132 }
00133 };
00134
00135 class DAG_NodeError: public std::exception
00136 {
00137 protected:
00138 std::string m_node_name;
00139 std::string m_msg;
00140 public:
00141 DAG_NodeError(std::string const& node_name)
00142 : m_node_name(node_name) { }
00143 virtual char const* what() throw()
00144 {
00145 m_msg = "Invalid node " + m_node_name;
00146 return m_msg.c_str();
00147 }
00148 std::string node() const { return m_node_name; }
00149 virtual ~DAG_NodeError() throw() { };
00150 };
00151
00152 class NeitherAdNorFile: public DAG_NodeError
00153 {
00154 public:
00155 virtual char const* what() throw()
00156 {
00157 m_msg = "Neither 'ad' nor 'file' specified" +
00158 (m_node_name.empty() ? "" : " for node " + m_node_name);
00159 return m_msg.c_str();
00160 }
00161 NeitherAdNorFile(std::string const& node)
00162 : DAG_NodeError(node) { }
00163 };
00164
00165 class BothAdAndFile: public DAG_NodeError
00166 {
00167 public:
00168 virtual char const* what() throw()
00169 {
00170 m_msg = "Both 'ad' and 'file' specified" +
00171 (m_node_name.empty() ? "" : " for node " + m_node_name);
00172 return m_msg.c_str();
00173 }
00174 BothAdAndFile(std::string const& node)
00175 : DAG_NodeError(node) { }
00176 };
00177
00178 class InvalidDescriptionFilename: public DAG_NodeError
00179 {
00180 std::string m_description;
00181 public:
00182 virtual char const* what() throw()
00183 {
00184 m_msg = "'file' not valid" +
00185 (m_description.empty() ? "" : " (" + m_description + ")");
00186 (m_node_name.empty() ? "" : " for node " + m_node_name);
00187 return m_msg.c_str();
00188 }
00189 InvalidDescriptionFilename(
00190 std::string const& node,
00191 std::string const& description
00192 )
00193 : DAG_NodeError(node), m_description(description) { }
00194 virtual ~InvalidDescriptionFilename() throw() { };
00195 };
00196
00197 class InvalidDescription: public DAG_NodeError
00198 {
00199 public:
00200 virtual char const* what() throw()
00201 {
00202 m_msg = "'description' not valid" +
00203 (m_node_name.empty() ? "" : " for node " + m_node_name);
00204 return m_msg.c_str();
00205 }
00206 InvalidDescription(std::string const& node)
00207 : DAG_NodeError(node) { }
00208 };
00209
00210 class InvalidRetryCount: public DAG_NodeError
00211 {
00212 public:
00213 virtual char const* what() throw()
00214 {
00215 m_msg = "'node_retry_count' must be an integer >= 0" +
00216 (m_node_name.empty() ? "" : " for node " + m_node_name);
00217 return m_msg.c_str();
00218 }
00219 InvalidRetryCount(std::string const& node)
00220 : DAG_NodeError(node) { }
00221 };
00222
00223 class InvalidNodeType: public DAG_NodeError
00224 {
00225 std::string m_type;
00226 public:
00227 virtual char const* what() throw()
00228 {
00229 m_msg = "node_type not valid" +
00230 (m_type.empty() ? "" : " (" + m_type + ")");
00231 (m_node_name.empty() ? "" : " for node " + m_node_name);
00232 return m_msg.c_str();
00233 }
00234 InvalidNodeType(std::string const& node, std::string const& type)
00235 : DAG_NodeError(node), m_type(type) { }
00236 virtual ~InvalidNodeType() throw() { };
00237 };
00238
00239 class DAGNodeInfo
00240 {
00241 class Implementation;
00242 boost::shared_ptr<Implementation> m_impl;
00243
00244 public:
00245 DAGNodeInfo();
00246 DAGNodeInfo(classad::ClassAd const& node_description,
00247 std::string const& node_type = std::string(),
00248 std::string const& node_name = std::string()
00249 );
00250 ~DAGNodeInfo() { };
00251
00252 public:
00253 std::string description_file() const;
00254 bool replace_description_file(std::string const& file);
00255 classad::ClassAd const* description_ad() const;
00256 bool replace_description_ad(classad::ClassAd* ad);
00257 bool description_file_for_ad(std::string const& file);
00258 bool description_ad_for_file(classad::ClassAd* ad);
00259
00260 std::string type() const;
00261
00262 int retry_count() const;
00263 bool retry_count(int n);
00264
00265 classad::ClassAd as_classad() const;
00266 };
00267
00268 class DAGAdNodeIterator
00269 : public std::iterator<
00270 std::input_iterator_tag
00271 ,std::pair<std::string, DAGNodeInfo>
00272 ,ptrdiff_t
00273 ,std::pair<std::string, DAGNodeInfo> const*
00274 ,std::pair<std::string, DAGNodeInfo> const&
00275 >
00276 {
00277 friend bool operator==(DAGAdNodeIterator const& lhs,
00278 DAGAdNodeIterator const& rhs
00279 );
00280
00281 classad::ClassAd const* m_nodes;
00282 classad::ClassAd::const_iterator m_node;
00283 value_type m_value;
00284
00285 bool is_good() const
00286 {
00287 return m_node != m_nodes->end();
00288 }
00289
00290 void set_value();
00291
00292 public:
00293
00294 DAGAdNodeIterator();
00295 ~DAGAdNodeIterator() {};
00296 DAGAdNodeIterator(classad::ClassAd const* nodes,
00297 classad::ClassAd::const_iterator it
00298 );
00299 DAGAdNodeIterator(DAGAdNodeIterator const& other);
00300 DAGAdNodeIterator& operator=(DAGAdNodeIterator const& other);
00301 DAGAdNodeIterator& operator++();
00302 DAGAdNodeIterator operator++(int);
00303 reference operator*() const;
00304
00305 pointer operator->() const
00306 {
00307 return &(operator*());
00308 }
00309
00310 };
00311
00312 inline bool operator==(DAGAdNodeIterator const& lhs,
00313 DAGAdNodeIterator const& rhs
00314 ) {
00315 return lhs.m_nodes == rhs.m_nodes && lhs.m_node == rhs.m_node;
00316 }
00317
00318 inline bool operator!=(DAGAdNodeIterator const& lhs,
00319 DAGAdNodeIterator const& rhs
00320 ) {
00321 return !(lhs == rhs);
00322 }
00323
00324 struct DAGAdDependencyIterator
00325 : public std::iterator<
00326 std::input_iterator_tag
00327 ,std::pair<DAGAdNodeIterator, DAGAdNodeIterator>
00328 ,ptrdiff_t
00329 ,std::pair<DAGAdNodeIterator, DAGAdNodeIterator> const*
00330 ,std::pair<DAGAdNodeIterator, DAGAdNodeIterator> const&
00331 >
00332 {
00333 friend bool operator==(DAGAdDependencyIterator const& lhs,
00334 DAGAdDependencyIterator const& rhs);
00335
00336 typedef DAGAdNodeIterator node_iterator;
00337 typedef classad::ExprList::iterator Iterator;
00338
00339 classad::ClassAd const* m_dag;
00340 Iterator m_dep;
00341 Iterator m_dep_end;
00342 Iterator m_parent;
00343 Iterator m_child;
00344 value_type m_value;
00345
00346 static classad::ExprList* parents(classad::ExprTree* dep)
00347 {
00348 assert(utilities::is_expression_list(dep));
00349 classad::ExprTree* et = *static_cast<classad::ExprList*>(dep)->begin();
00350 assert(utilities::is_expression_list(et));
00351 return static_cast<classad::ExprList*>(et);
00352 }
00353 static classad::ExprList* children(classad::ExprTree* dep)
00354 {
00355 assert(utilities::is_expression_list(dep));
00356 classad::ExprTree* et = *++static_cast<classad::ExprList*>(dep)->begin();
00357 assert(utilities::is_expression_list(et));
00358 return static_cast<classad::ExprList*>(et);
00359 }
00360 bool is_good() const { return m_dep != m_dep_end; }
00361 void set_value();
00362
00363 DAGAdDependencyIterator(classad::ClassAd const* dag = 0, bool begin = false);
00364
00365
00366
00367 DAGAdDependencyIterator& operator++();
00368 DAGAdDependencyIterator operator++(int);
00369
00370 reference operator*() const
00371 {
00372 return m_value;
00373 }
00374
00375 pointer operator->() const
00376 {
00377 return &(operator*());
00378 }
00379 };
00380
00381 inline bool operator==(DAGAdDependencyIterator const& lhs,
00382 DAGAdDependencyIterator const& rhs)
00383 {
00384 return (!lhs.is_good() && !rhs.is_good())
00385 || (lhs.is_good() && rhs.is_good()
00386 && lhs.m_dep == rhs.m_dep
00387 && lhs.m_parent == rhs.m_parent
00388 && lhs.m_child == rhs.m_child
00389 );
00390 }
00391
00392 inline bool operator!=(DAGAdDependencyIterator const& lhs,
00393 DAGAdDependencyIterator const& rhs)
00394 {
00395 return !(lhs == rhs);
00396 }
00397
00398 class DAGAd: boost::noncopyable
00399 {
00400 public:
00401
00402 typedef DAGAdNodeIterator node_iterator;
00403 typedef DAGAdNodeIterator::value_type node_value_type;
00404 typedef DAGAdDependencyIterator dependency_iterator;
00405 typedef DAGAdDependencyIterator::value_type dependency_value_type;
00406
00407 typedef boost::property<
00408 boost::vertex_name_t, std::string, boost::property<
00409 boost::vertex_color_t, boost::default_color_type
00410 > > VertexProperties;
00411
00412 typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS, VertexProperties> Graph_t;
00413 typedef boost::graph_traits<Graph_t>::vertex_descriptor Vertex;
00414 typedef boost::graph_traits<Graph_t >::vertex_iterator VertexIterator;
00415 typedef boost::graph_traits<Graph_t>::in_edge_iterator InEdgeIterator;
00416
00417 private:
00418 boost::shared_ptr<classad::ClassAd> m_ad;
00419 Graph_t m_graph;
00420
00421 public:
00422 DAGAd();
00423 explicit DAGAd(classad::ClassAd const& ad);
00424
00425 Graph_t& graph() { return m_graph; }
00426 classad::ClassAd const& ad() const;
00427
00428
00429
00430
00431 std::string default_node_type(std::string const& new_value);
00432
00433
00434
00435 std::string default_node_type() const;
00436
00437
00438
00439
00440 int default_node_retry_count(int new_value);
00441
00442
00443
00444 int default_node_retry_count() const;
00445
00446 bool add_node(std::string const& name, DAGNodeInfo const& info);
00447 bool replace_node(std::string const& name, DAGNodeInfo const& info);
00448 bool remove_node(std::string const& name);
00449 std::size_t num_nodes() const;
00450 node_iterator find(std::string const& name) const;
00451
00452 bool add_dependency(std::string const& first, std::string const& second);
00453 bool remove_dependency(std::string const& first, std::string const& second);
00454 std::size_t num_dependencies() const;
00455
00456 bool set_generic(std::string const& attribute, classad::ExprTree* value);
00457 classad::ExprTree const* get_generic(std::string const& attribute) const;
00458 bool remove_generic(std::string const& attribute);
00459
00460 std::pair<dependency_iterator, dependency_iterator> classad_dependencies() const;
00461 std::pair<node_iterator, node_iterator> nodes() const;
00462
00463 struct Attributes
00464 {
00465 static std::string const TYPE;
00466 static std::string const NODES;
00467 static std::string const DEPENDENCIES;
00468 static std::string const NODE_RETRY_COUNT;
00469 static std::string const NODE_TYPE;
00470 static std::string const DESCRIPTION_FILE;
00471 static std::string const DESCRIPTION_AD;
00472 };
00473 };
00474
00475 }
00476 }
00477
00478 #endif