00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef EDG_WORKLOAD_COMMON_UTILITIES_CLASSAD_UTILS_H
00012 #define EDG_WORKLOAD_COMMON_UTILITIES_CLASSAD_UTILS_H
00013
00014 #include <string>
00015 #include <vector>
00016 #include <stack>
00017 #include <numeric>
00018 #include <functional>
00019 #include <algorithm>
00020 #include <classad_distribution.h>
00021 #include <iostream>
00022
00023 namespace edg {
00024 namespace workload {
00025 namespace common {
00026 namespace utilities {
00027
00028 inline void setValue(classad::Value& value, const std::string& s) { value.SetStringValue(s); }
00029 inline void setValue(classad::Value& value, double d) { value.SetRealValue(d); }
00030 inline void setValue(classad::Value& value, bool b) { value.SetBooleanValue(b); }
00031 inline void setValue(classad::Value& value, int i) { value.SetIntegerValue(i); }
00032
00033 inline bool getValue(const classad::Value& value, std::string& s) { return value.IsStringValue(s); }
00034 inline bool getValue(const classad::Value& value, double& d) { return value.IsRealValue(d); }
00035 inline bool getValue(const classad::Value& value, bool& b) { return value.IsBooleanValue(b); }
00036 inline bool getValue(const classad::Value& value, int& i) { return value.IsIntegerValue(i); }
00037
00038 template<class T>
00039 struct InsertExprInVector : public std::binary_function<std::vector<T>*, classad::ExprTree*, std::vector<T>* >
00040 {
00041 std::vector<T>* operator()(std::vector<T>* v, classad::ExprTree* e) {
00042 classad::Value value;
00043
00044 #ifndef WITH_UI_JCLIENT
00045 dynamic_cast<classad::Literal*>(e) -> GetValue(value);
00046 #else
00047 ((classad::Literal*)(e)) -> GetValue(value);
00048 #endif
00049
00050 T s;
00051 if( getValue(value,s) ) v -> push_back( s );
00052 return v;
00053 }
00054 };
00055
00056 template<class T>
00057 bool EvaluateAttrList(const classad::ClassAd& ad, const std::string& what, std::vector<T>&l)
00058 {
00059 bool res = false;
00060 std::string where;
00061 classad::Value list_value;
00062 const classad::ExprList *expr_list;
00063
00064 if( ad.EvaluateAttr(what, list_value) == true &&
00065 list_value.IsListValue( expr_list ) == true ) {
00066 accumulate(expr_list -> begin(), expr_list -> end(), &l, InsertExprInVector<T>());
00067 res = true;
00068 }
00069
00070 return res;
00071 }
00072
00073 template<class T>
00074 bool EvaluateAttrListOrSingle(const classad::ClassAd& ad, const std::string& what, std::vector<T>&l)
00075 {
00076 bool res = false;
00077 if ( !(res = EvaluateAttrList(ad, what, l)) ) {
00078
00079 classad::Value v;
00080 T tmpvalue;
00081 if ( res = (ad.EvaluateAttr(what, v) && getValue(v, tmpvalue) ) ) {
00082 l.push_back(tmpvalue);
00083 }
00084 }
00085 return res;
00086 }
00087
00088 template<class T>
00089 T EvaluateExpr(classad::ClassAd& ad, const std::string& what)
00090 {
00091 classad::Value v;
00092 T t;
00093 assert(ad.EvaluateExpr(what, v) && getValue(v,t));
00094 return t;
00095 }
00096
00097 template<class T>
00098 bool InsertAttrList(classad::ClassAd& ad, const std::string& what, const std::vector<T>&l)
00099 {
00100 classad::ExprList* expr_list = asExprList(l);
00101
00102 if( !expr_list ) return false;
00103
00104 expr_list -> SetParentScope( &ad );
00105 return ad.Insert(what,expr_list);
00106 }
00107
00108 inline std::string asString(classad::ClassAd& ad)
00109 {
00110 std::string s;
00111 classad::ClassAdUnParser unparser;
00112 classad::Value value;
00113
00114 value.SetClassAdValue(&ad);
00115 unparser.Unparse(s, value);
00116
00117 return s;
00118 }
00119
00120 template<class T>
00121 classad::ExprList* asExprList(const std::vector<T>& v)
00122 {
00123 std::vector< classad::ExprTree* > list;
00124 typename std::vector<T>::const_iterator it;
00125
00126 for(it = v.begin(); it != v.end(); it++) {
00127 classad::Value value;
00128 setValue(value, (*it));
00129 list.push_back( static_cast<classad::ExprTree*>(classad::Literal::MakeLiteral(value)));
00130 }
00131
00132 classad::ExprList* result = NULL;
00133
00134 result = classad::ExprList::MakeExprList(list);
00135
00136 return result;
00137 }
00138
00139 typedef std::list<classad::ExprTree*> expression_trace_type;
00140 typedef std::pair<expression_trace_type*, classad::AttributeReference*> predicate_context_type;
00141 typedef std::unary_function<predicate_context_type, bool> unary_predicate;
00142
00143 struct is_reference_to : public unary_predicate
00144 {
00145 is_reference_to(const std::string& r) : ref(r) {}
00146 bool operator()(const predicate_context_type& ctx) const {
00147
00148 classad::ExprTree* reference_expr = 0;
00149 std::string name;
00150 bool absolute;
00151 ctx.second -> GetComponents(reference_expr, name, absolute);
00152 if( reference_expr &&
00153 reference_expr -> GetKind() == classad::ExprTree::ATTRREF_NODE ) {
00154 classad::ExprTree* e;
00155 dynamic_cast<classad::AttributeReference*>(reference_expr) -> GetComponents(e, name, absolute);
00156 return name == ref;
00157 }
00158 return false;
00159 }
00160 std::string ref;
00161 };
00162
00163 struct is_absolute_reference : public unary_predicate
00164 {
00165 bool operator()(const predicate_context_type& ctx) const {
00166 classad::ExprTree* reference_expr = 0;
00167 std::string name;
00168 bool absolute;
00169 ctx.second -> GetComponents(reference_expr, name, absolute);
00170 return absolute;
00171 }
00172
00173 };
00174
00175 struct always : unary_predicate
00176 {
00177 bool operator()(const predicate_context_type& ctx) const { return true; }
00178 };
00179
00180 struct is_function_call_to : public std::unary_function<classad::ExprTree*, bool>
00181 {
00182 is_function_call_to(const std::string& fn) : fn_name( fn ) {}
00183 bool operator()(classad::ExprTree* e) const {
00184 if( e->GetKind() != classad::ExprTree::FN_CALL_NODE ) return false;
00185 std::vector<classad::ExprTree*> args;
00186 std::string fn;
00187 dynamic_cast<classad::FunctionCall*>(e) -> GetComponents(fn, args);
00188 return fn == fn_name;
00189 }
00190 std::string fn_name;
00191 };
00192
00193 struct is_operand_of : public unary_predicate
00194 {
00195 is_operand_of(const std::string& fn) : fn_name( fn ) {}
00196 bool operator()(const predicate_context_type& ctx) const {
00197 return find_if(ctx.first->begin(), ctx.first->end(), is_function_call_to(fn_name)) != ctx.first->end();
00198 }
00199 std::string fn_name;
00200 };
00201
00202 struct is_rightmost_operand_of : public unary_predicate
00203 {
00204 is_rightmost_operand_of(const std::string& fn) : fn_name( fn ) {}
00205 bool operator()(const predicate_context_type& ctx) const {
00206 expression_trace_type::const_iterator it = find_if(ctx.first->begin(), ctx.first->end(), is_function_call_to(fn_name));
00207 if( it == ctx.first->end() ) return false;
00208
00209 std::vector<classad::ExprTree*> args;
00210 std::string fn;
00211 dynamic_cast<classad::FunctionCall*>(*it) -> GetComponents(fn, args);
00212 return ctx.second == args.back();
00213 }
00214 std::string fn_name;
00215 };
00216
00217 template<class Function>
00218 std::vector<std::string>* insertAttributeInVector(std::vector<std::string>* v, classad::ExprTree* e, expression_trace_type* exprTrace, Function predicate)
00219 {
00220 if( !e ) return v;
00221 if( find(exprTrace->begin(), exprTrace->end(), e) != exprTrace->end() ) return v;
00222
00223 exprTrace -> push_front(e);
00224 switch( e -> GetKind() ) {
00225 case classad::ExprTree::LITERAL_NODE: break;
00226
00227 case classad::ExprTree::OP_NODE: {
00228 classad::ExprTree* e1 = 0, *e2 = 0, *e3 = 0;
00229 classad::Operation::OpKind ok;
00230 dynamic_cast<classad::Operation*>(e) -> GetComponents(ok, e1, e2, e3);
00231 if( e1 ) insertAttributeInVector(v, e1, exprTrace, predicate);
00232 if( e2 ) insertAttributeInVector(v, e2, exprTrace, predicate);
00233 if( e3 ) insertAttributeInVector(v, e3, exprTrace, predicate);
00234 }
00235 break;
00236 case classad::ExprTree::FN_CALL_NODE: {
00237 std::vector<classad::ExprTree*> args;
00238 std::string fn;
00239 dynamic_cast<classad::FunctionCall*>(e) -> GetComponents(fn, args);
00240 for(std::vector<classad::ExprTree*>::const_iterator it = args.begin();
00241 it != args.end(); it++) insertAttributeInVector(v,*it, exprTrace, predicate);
00242 }
00243 break;
00244 case classad::ExprTree::EXPR_LIST_NODE: {
00245 std::vector<classad::ExprTree*> args;
00246 dynamic_cast<classad::ExprList*>(e) -> GetComponents(args);
00247 for(std::vector<classad::ExprTree*>::const_iterator it = args.begin();
00248 it != args.end(); it++) insertAttributeInVector(v,*it, exprTrace, predicate);
00249 }
00250 break;
00251 case classad::ExprTree::ATTRREF_NODE: {
00252
00253 classad::AttributeReference* a = dynamic_cast<classad::AttributeReference*>(e);
00254 classad::ExprTree* reference_expr = 0;
00255 std::string name;
00256 bool absolute;
00257 a -> GetComponents(reference_expr, name, absolute);
00258 if(!reference_expr) {
00259 reference_expr = a -> GetParentScope() -> Lookup(name);
00260 if(reference_expr && reference_expr != e) insertAttributeInVector(v, reference_expr, exprTrace, predicate);
00261 }
00262 else {
00263 if( predicate(std::make_pair(exprTrace,a)) &&
00264 find(v -> begin(), v->end(), name) == v->end() ) v -> push_back(name);
00265 }
00266 }
00267 break;
00268 default:
00269 assert( false );
00270 }
00271 exprTrace -> pop_front();
00272 return v;
00273 }
00274
00275 template<class Function>
00276 std::vector<std::string>* insertAttributeInVector(std::vector<std::string>* v, classad::ExprTree* e, Function predicate)
00277 {
00278 expression_trace_type exprTrace;
00279 return insertAttributeInVector(v,e,&exprTrace, predicate);
00280 }
00281
00282 inline std::vector<std::string>* insertAttributeInVector(std::vector<std::string>* v, classad::ExprTree* e)
00283 {
00284 expression_trace_type exprTrace;
00285 return insertAttributeInVector(v,e,&exprTrace, always());
00286 }
00287
00288 class ClassAdError: public std::exception
00289 {
00290 public:
00291 ~ClassAdError() throw() {};
00292 char const* what() const throw()
00293 {
00294 return "ClassAd utils - generic error";
00295 }
00296 };
00297
00298 class CannotParseClassAd: public ClassAdError
00299 {
00300 std::string m_what;
00301 std::string m_str;
00302 public:
00303 CannotParseClassAd()
00304 : m_what("ClassAd utils - cannot parse classad")
00305 {
00306 }
00307 CannotParseClassAd(std::string const& ad_str)
00308 : m_what("ClassAd utils - cannot parse classad: " + ad_str),
00309 m_str(ad_str)
00310 {
00311 }
00312 ~CannotParseClassAd() throw() {}
00313 std::string str() const
00314 {
00315 return m_str;
00316 }
00317 char const* what() const throw()
00318 {
00319 return m_what.c_str();
00320 }
00321 };
00322
00323 class nothrow_t {};
00324 extern nothrow_t const nothrow;
00325
00326
00327 classad::ClassAd* parse_classad(std::string const& s);
00328
00329 classad::ClassAd* parse_classad(std::string const& s, nothrow_t const&);
00330
00331
00332 classad::ClassAd* parse_classad(std::istream& is);
00333
00334 std::string unparse_classad(classad::ClassAd const& ad);
00335
00336 class InvalidValue: public ClassAdError
00337 {
00338 std::string m_what;
00339 public:
00340 InvalidValue(std::string const& expression, std::string const& type)
00341 : m_what("ClassAd error: attribute \"" + expression
00342 + "\" does not exist or has the wrong type (expecting \"" + type + "\")")
00343 {
00344 }
00345 ~InvalidValue() throw()
00346 {
00347 }
00348 char const* what() const throw()
00349 {
00350 return m_what.c_str();
00351 }
00352 };
00353
00354 class ValueProxy
00355 {
00356 std::string m_expression;
00357 classad::Value m_value;
00358 public:
00359 ValueProxy(std::string const& e, classad::Value const& v);
00360
00361 operator bool() const;
00362 operator int() const;
00363 operator double() const;
00364 operator std::string() const;
00365 operator classad::ClassAd const*() const;
00366 operator classad::ExprList const*() const;
00367 };
00368
00369 ValueProxy evaluate_attribute(classad::ClassAd const& ad,
00370 std::string const& attribute);
00371
00372 ValueProxy evaluate_expression(classad::ClassAd const& ad,
00373 std::string const& expression);
00374
00375 bool match(classad::ClassAd const& lhs,
00376 classad::ClassAd const& rhs,
00377 std::string const& match_type);
00378
00379 bool left_matches_right (classad::ClassAd const& lhs, classad::ClassAd const& rhs);
00380 bool right_matches_left (classad::ClassAd const& lhs, classad::ClassAd const& rhs);
00381 bool symmetric_match (classad::ClassAd const& lhs, classad::ClassAd const& rhs);
00382
00383 class UndefinedRank: public ClassAdError
00384 {
00385 public:
00386 ~UndefinedRank() throw() {}
00387 char const* what() const throw()
00388 {
00389 return "ClassAd utils - undefined rank";
00390 }
00391 };
00392
00393 double rank(classad::ClassAd const& lhs,
00394 classad::ClassAd const& rhs,
00395 std::string const& rank_type);
00396
00397 double left_rank(classad::ClassAd const& lhs,
00398 classad::ClassAd const& rhs);
00399
00400 double right_rank(classad::ClassAd const& lhs,
00401 classad::ClassAd const& rhs);
00402
00403
00404
00405 bool evaluate_attribute(classad::ClassAd const& ad,
00406 std::string const& attribute,
00407 std::string& value);
00408
00409 bool evaluate_expression(classad::ClassAd const& ad,
00410 std::string const& expression,
00411 std::string& value);
00412
00413 bool evaluate_expression(classad::ClassAd const& ad,
00414 std::string const& expression,
00415 classad::ClassAd const*& value);
00416
00417 }}}}
00418
00419 #endif
00420
00421
00422
00423