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
00222 exprTrace -> push_front(e);
00223 switch( e -> GetKind() ) {
00224 case classad::ExprTree::LITERAL_NODE: break;
00225
00226 case classad::ExprTree::OP_NODE: {
00227 classad::ExprTree* e1 = 0, *e2 = 0, *e3 = 0;
00228 classad::Operation::OpKind ok;
00229 dynamic_cast<classad::Operation*>(e) -> GetComponents(ok, e1, e2, e3);
00230 if( e1 ) insertAttributeInVector(v, e1, exprTrace, predicate);
00231 if( e2 ) insertAttributeInVector(v, e2, exprTrace, predicate);
00232 if( e3 ) insertAttributeInVector(v, e3, exprTrace, predicate);
00233 }
00234 break;
00235 case classad::ExprTree::FN_CALL_NODE: {
00236 std::vector<classad::ExprTree*> args;
00237 std::string fn;
00238 dynamic_cast<classad::FunctionCall*>(e) -> GetComponents(fn, args);
00239 for(std::vector<classad::ExprTree*>::const_iterator it = args.begin();
00240 it != args.end(); it++) insertAttributeInVector(v,*it, exprTrace, predicate);
00241 }
00242 break;
00243 case classad::ExprTree::EXPR_LIST_NODE: {
00244 std::vector<classad::ExprTree*> args;
00245 dynamic_cast<classad::ExprList*>(e) -> GetComponents(args);
00246 for(std::vector<classad::ExprTree*>::const_iterator it = args.begin();
00247 it != args.end(); it++) insertAttributeInVector(v,*it, exprTrace, predicate);
00248 }
00249 break;
00250 case classad::ExprTree::ATTRREF_NODE: {
00251
00252 classad::AttributeReference* a = dynamic_cast<classad::AttributeReference*>(e);
00253 classad::ExprTree* reference_expr = 0;
00254 std::string name;
00255 bool absolute;
00256 a -> GetComponents(reference_expr, name, absolute);
00257 if(!reference_expr) {
00258 reference_expr = a -> GetParentScope() -> Lookup(name);
00259 if(reference_expr) insertAttributeInVector(v, reference_expr, exprTrace, predicate);
00260 }
00261 else {
00262 if( predicate(std::make_pair(exprTrace,a)) &&
00263 find(v -> begin(), v->end(), name) == v->end() ) v -> push_back(name);
00264 }
00265 }
00266 break;
00267 default:
00268 assert( false );
00269 }
00270 exprTrace -> pop_front();
00271 return v;
00272 }
00273
00274 template<class Function>
00275 std::vector<std::string>* insertAttributeInVector(std::vector<std::string>* v, classad::ExprTree* e, Function predicate)
00276 {
00277 expression_trace_type exprTrace;
00278 return insertAttributeInVector(v,e,&exprTrace, predicate);
00279 }
00280
00281 inline std::vector<std::string>* insertAttributeInVector(std::vector<std::string>* v, classad::ExprTree* e)
00282 {
00283 expression_trace_type exprTrace;
00284 return insertAttributeInVector(v,e,&exprTrace, always());
00285 }
00286
00287 class ClassAdError: public std::exception
00288 {
00289 public:
00290 ~ClassAdError() throw() {};
00291 char const* what() const throw()
00292 {
00293 return "ClassAd utils - generic error";
00294 }
00295 };
00296
00297 class CannotParseClassAd: public ClassAdError
00298 {
00299 std::string m_what;
00300 std::string m_str;
00301 public:
00302 CannotParseClassAd()
00303 : m_what("ClassAd utils - cannot parse classad")
00304 {
00305 }
00306 CannotParseClassAd(std::string const& ad_str)
00307 : m_what("ClassAd utils - cannot parse classad: " + ad_str),
00308 m_str(ad_str)
00309 {
00310 }
00311 ~CannotParseClassAd() throw() {}
00312 std::string str() const
00313 {
00314 return m_str;
00315 }
00316 char const* what() const throw()
00317 {
00318 return m_what.c_str();
00319 }
00320 };
00321
00322 class nothrow_t {};
00323 extern nothrow_t const nothrow;
00324
00325
00326 classad::ClassAd* parse_classad(std::string const& s);
00327
00328 classad::ClassAd* parse_classad(std::string const& s, nothrow_t const&);
00329
00330
00331 classad::ClassAd* parse_classad(std::istream& is);
00332
00333 std::string unparse_classad(classad::ClassAd const& ad);
00334
00335 class InvalidValue: public ClassAdError
00336 {
00337 std::string m_what;
00338 public:
00339 InvalidValue(std::string const& expression, std::string const& type)
00340 : m_what("ClassAd error: attribute \"" + expression
00341 + "\" does not exist or has the wrong type (expecting \"" + type + "\")")
00342 {
00343 }
00344 ~InvalidValue() throw()
00345 {
00346 }
00347 char const* what() const throw()
00348 {
00349 return m_what.c_str();
00350 }
00351 };
00352
00353 class ValueProxy
00354 {
00355 std::string m_expression;
00356 classad::Value m_value;
00357 public:
00358 ValueProxy(std::string const& e, classad::Value const& v);
00359
00360 operator bool() const;
00361 operator int() const;
00362 operator double() const;
00363 operator std::string() const;
00364 operator classad::ClassAd const*() const;
00365 operator classad::ExprList const*() const;
00366 };
00367
00368 ValueProxy evaluate_attribute(classad::ClassAd const& ad,
00369 std::string const& attribute);
00370
00371 ValueProxy evaluate_expression(classad::ClassAd const& ad,
00372 std::string const& expression);
00373
00374 bool match(classad::ClassAd const& lhs,
00375 classad::ClassAd const& rhs,
00376 std::string const& match_type);
00377
00378 bool left_matches_right (classad::ClassAd const& lhs, classad::ClassAd const& rhs);
00379 bool right_matches_left (classad::ClassAd const& lhs, classad::ClassAd const& rhs);
00380 bool symmetric_match (classad::ClassAd const& lhs, classad::ClassAd const& rhs);
00381
00382 class UndefinedRank: public ClassAdError
00383 {
00384 public:
00385 ~UndefinedRank() throw() {}
00386 char const* what() const throw()
00387 {
00388 return "ClassAd utils - undefined rank";
00389 }
00390 };
00391
00392 double rank(classad::ClassAd const& lhs,
00393 classad::ClassAd const& rhs,
00394 std::string const& rank_type);
00395
00396 double left_rank(classad::ClassAd const& lhs,
00397 classad::ClassAd const& rhs);
00398
00399 double right_rank(classad::ClassAd const& lhs,
00400 classad::ClassAd const& rhs);
00401
00402
00403
00404 bool evaluate_attribute(classad::ClassAd const& ad,
00405 std::string const& attribute,
00406 std::string& value);
00407
00408 bool evaluate_expression(classad::ClassAd const& ad,
00409 std::string const& expression,
00410 std::string& value);
00411
00412 bool evaluate_expression(classad::ClassAd const& ad,
00413 std::string const& expression,
00414 classad::ClassAd const*& value);
00415
00416 }}}}
00417
00418 #endif
00419
00420
00421
00422