From: Michael Andres Date: Thu, 3 Sep 2009 11:32:40 +0000 (+0200) Subject: Fix serialization and restore of predicated PoolQueries. X-Git-Tag: 6.14.0~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=01a86ee1d30763761af61d842b464bf2e6794f2d;p=platform%2Fupstream%2Flibzypp.git Fix serialization and restore of predicated PoolQueries. --- diff --git a/zypp/PoolQuery.cc b/zypp/PoolQuery.cc index 5f7f51c..e129598 100644 --- a/zypp/PoolQuery.cc +++ b/zypp/PoolQuery.cc @@ -39,6 +39,110 @@ namespace zypp namespace { ///////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// + // some Helpers and Predicates + ///////////////////////////////////////////////////////////////// + + bool isDependencyAttribute( sat::SolvAttr attr_r ) + { + static sat::SolvAttr deps[] = { + SolvAttr::provides, + SolvAttr::requires, + SolvAttr::recommends, + SolvAttr::obsoletes, + SolvAttr::conflicts, + SolvAttr::suggests, + SolvAttr::supplements, + SolvAttr::enhances, + }; + for_( it, arrayBegin(deps), arrayEnd(deps) ) + if ( *it == attr_r ) + return true; + return false; + } + + /** Whether the current capabilities edition range ovelaps. + * Query asserts \a iter_r points to a capability and we + * have to check the range only. + */ + struct EditionRangePredicate + { + EditionRangePredicate( const Rel & op, const Edition & edition ) + : _range( op, edition ) + {} + + bool operator()( sat::LookupAttr::iterator iter_r ) + { + CapDetail cap( iter_r.id() ); + if ( ! cap.isSimple() ) + return false; + if ( cap.isNamed() ) // no range to match + return true; + return overlaps( Edition::MatchRange( cap.op(), cap.ed() ), _range ); + } + + std::string serialize() const + { + std::string ret( "EditionRange" ); + str::appendEscaped( ret, _range.op.asString() ); + str::appendEscaped( ret, _range.value.asString() ); + return ret; + } + + Edition::MatchRange _range; + }; + + /** Whether the current Solvables edition is within a given range. */ + struct SolvableRangePredicate + { + SolvableRangePredicate( const Rel & op, const Edition & edition ) + : _range( op, edition ) + {} + + bool operator()( sat::LookupAttr::iterator iter_r ) + { + return overlaps( Edition::MatchRange( Rel::EQ, iter_r.inSolvable().edition() ), _range ); + } + + std::string serialize() const + { + std::string ret( "SolvableRange" ); + str::appendEscaped( ret, _range.op.asString() ); + str::appendEscaped( ret, _range.value.asString() ); + return ret; + } + + Edition::MatchRange _range; + }; + + /** Whether the current capability matches a given one. + * Query asserts \a iter_r points to a capability and we + * have to check the match only. + */ + struct CapabilityMatchPredicate + { + CapabilityMatchPredicate( Capability cap_r ) + : _cap( cap_r ) + {} + + bool operator()( sat::LookupAttr::iterator iter_r ) const + { + return _cap.matches( iter_r.asType() ) == CapMatch::yes; + } + + std::string serialize() const + { + std::string ret( "CapabilityMatch" ); + str::appendEscaped( ret, _cap.asString() ); + return ret; + } + + Capability _cap; + }; + + ///////////////////////////////////////////////////////////////// + // + ///////////////////////////////////////////////////////////////// /** Match data per attribtue. * * This includes the attribute itself, an optional \ref sat::AttrMatcher @@ -64,6 +168,9 @@ namespace zypp static bool always( sat::LookupAttr::iterator ) { return true; } static bool never( sat::LookupAttr::iterator ) { return false; } + AttrMatchData() + {} + AttrMatchData( sat::SolvAttr attr_r, const sat::AttrMatcher & attrMatcher_r ) : attr( attr_r ) , attrMatcher( attrMatcher_r ) @@ -77,18 +184,84 @@ namespace zypp , predicateStr( predicateStr_r ) {} - /** A usable Predicate must provide a string representation. + /** A usable Predicate must provide a string serialization. * As there is no \c operator== for \ref Predicate, we compare it's - * string representation instead. Actually Predicate deserves to become - * a class which is also serializable, so we can store predicated queries. + * string representation instead. If you add new predicated, check the + * deserialization code in \ref deserialize. */ template void addPredicate( const _Predicate & predicate_r ) { predicate = predicate_r; - predicateStr = predicate_r.stringRep(); + predicateStr = predicate_r.serialize(); + } + + /** Dumb serialization. + * \code + * AttrMatchData ATTRIBUTE SEARCHSTRING [C|X] SERIALIZED_PREDICATE + * \endcode + */ + std::string serialize() const + { + std::string ret( "AttrMatchData" ); + str::appendEscaped( ret, attr.asString() ); + str::appendEscaped( ret, attrMatcher.searchstring() ); + // TODO: Actually the flag should be serialized too, but for PoolQuery + // it's by now sufficient to differ between mode OTHER and others, + // i.e. whether to compile or not compile. + str::appendEscaped( ret, attrMatcher.flags().mode() == Match::OTHER ? "C" : "X" ); + str::appendEscaped( ret, predicateStr ); + return ret; } + /** Dumb restore from serialized string. + * \throw Exception on parse error. + */ + static AttrMatchData deserialize( const std::string & str_r ) + { + std::vector words; + str::splitEscaped( str_r, std::back_inserter(words) ); + if ( words.empty() || words[0] != "AttrMatchData" ) + ZYPP_THROW( Exception( str::Str() << "Expecting AttrMatchData: " << str_r ) ); + if ( words.size() != 5 ) + ZYPP_THROW( Exception( str::Str() << "Wrong number of words: " << str_r ) ); + + AttrMatchData ret; + ret.attr = sat::SolvAttr( words[1] ); + ret.attrMatcher = sat::AttrMatcher( words[2] ); + if ( words[3] == "C" ) + ret.attrMatcher.setFlags( Match::OTHER ); + ret.predicateStr = words[4]; + + // now the predicate + words.clear(); + str::splitEscaped( ret.predicateStr, std::back_inserter(words) ); + if ( ! words.empty() ) + { + if ( words[0] == "EditionRange" ) + { + if ( words.size() != 3 ) + ZYPP_THROW( Exception( str::Str() << "Wrong number of words: " << str_r ) ); + ret.predicate = EditionRangePredicate( Rel(words[1]), Edition(words[2]) ); + } + else if ( words[0] == "SolvableRange" ) + { + if ( words.size() != 3 ) + ZYPP_THROW( Exception( str::Str() << "Wrong number of words: " << str_r ) ); + ret.predicate = SolvableRangePredicate( Rel(words[1]), Edition(words[2]) ); + } + else if ( words[0] == "CapabilityMatch" ) + { + if ( words.size() != 2 ) + ZYPP_THROW( Exception( str::Str() << "Wrong number of words: " << str_r ) ); + ret.predicate = CapabilityMatchPredicate( Capability(words[1]) ); + } + else + ZYPP_THROW( Exception( str::Str() << "Unknown predicate: " << str_r ) ); + } + return ret; + } + sat::SolvAttr attr; sat::AttrMatcher attrMatcher; Predicate predicate; @@ -130,104 +303,6 @@ namespace zypp typedef std::list AttrMatchList; - ///////////////////////////////////////////////////////////////// - // some Helpers and Predicates - ///////////////////////////////////////////////////////////////// - - bool isDependencyAttribute( sat::SolvAttr attr_r ) - { - static sat::SolvAttr deps[] = { - SolvAttr::provides, - SolvAttr::requires, - SolvAttr::recommends, - SolvAttr::obsoletes, - SolvAttr::conflicts, - SolvAttr::suggests, - SolvAttr::supplements, - SolvAttr::enhances, - }; - for_( it, arrayBegin(deps), arrayEnd(deps) ) - if ( *it == attr_r ) - return true; - return false; - } - - /** Whether the current capabilities edition range ovelaps. - * Query asserts \a iter_r points to a capability and we - * have to check the range only. - */ - struct EditionRangePredicate - { - EditionRangePredicate( const Rel & op, const Edition & edition ) - : _range( op, edition ) - {} - - bool operator()( sat::LookupAttr::iterator iter_r ) - { - CapDetail cap( iter_r.id() ); - if ( ! cap.isSimple() ) - return false; - if ( cap.isNamed() ) // no range to match - return true; - return overlaps( Edition::MatchRange( cap.op(), cap.ed() ), _range ); - } - - std::string stringRep() const - { - std::ostringstream str; - str << "EditionRange " << _range.op << " " << _range.value; - return str.str(); - } - - Edition::MatchRange _range; - }; - - /** Whether the current Solvables edition is within a given range. */ - struct SolvableRangePredicate - { - SolvableRangePredicate( const Rel & op, const Edition & edition ) - : _range( op, edition ) - {} - - bool operator()( sat::LookupAttr::iterator iter_r ) - { - return overlaps( Edition::MatchRange( Rel::EQ, iter_r.inSolvable().edition() ), _range ); - } - - std::string stringRep() const - { - std::ostringstream str; - str << "SolvableRange " << _range.op << " " << _range.value; - return str.str(); - } - - Edition::MatchRange _range; - }; - - /** Whether the current capability matches a given one. - * Query asserts \a iter_r points to a capability and we - * have to check the match only. - */ - struct CapabilityMatchPredicate - { - CapabilityMatchPredicate( Capability cap_r ) - : _cap( cap_r ) - {} - - bool operator()( sat::LookupAttr::iterator iter_r ) const - { - return _cap.matches( iter_r.asType() ) == CapMatch::yes; - } - - std::string stringRep() const - { - std::ostringstream str; - str << "CapabilityMatch " << _cap; - return str.str(); - } - - Capability _cap; - }; } ///////////////////////////////////////////////////////////////// // namespace @@ -354,7 +429,7 @@ namespace zypp _attrMatchList.clear(); Match cflags( _flags ); - if ( cflags.mode() == Match::OTHER) // this will never succeed... + if ( cflags.mode() == Match::OTHER ) // this will never succeed... ZYPP_THROW( MatchUnknownModeException( cflags ) ); /** Compiled search strings. */ @@ -923,6 +998,7 @@ attremptycheckend: static const PoolQueryAttr caseSensitiveAttr; static const PoolQueryAttr installStatusAttr; static const PoolQueryAttr editionAttr; + static const PoolQueryAttr complexAttr; }; const PoolQueryAttr PoolQueryAttr::noAttr; @@ -935,6 +1011,7 @@ attremptycheckend: const PoolQueryAttr PoolQueryAttr::caseSensitiveAttr("case_sensitive"); const PoolQueryAttr PoolQueryAttr::installStatusAttr("install_status"); const PoolQueryAttr PoolQueryAttr::editionAttr("version"); + const PoolQueryAttr PoolQueryAttr::complexAttr("complex"); class StringTypeAttr : public IdStringType { @@ -969,6 +1046,7 @@ attremptycheckend: //\TODO maybe ctor with stream can be usefull + //\TODO let it throw, let it throw, let it throw. bool PoolQuery::recover( istream &str, char delim ) { bool finded_something = false; //indicates some atributes is finded @@ -1115,6 +1193,18 @@ attremptycheckend: setEdition(Edition(attrValue), rel); } + else if ( attribute == PoolQueryAttr::complexAttr ) + { + try + { + _pimpl->_uncompiledPredicated.insert( AttrMatchData::deserialize( attrValue ) ); + } + catch ( const Exception & err ) + { + WAR << "Unparsable value for complex: " << err.asUserHistory() << endl; + + } + } else if ( attribute==PoolQueryAttr::noAttr ) { WAR << "empty attribute name" << endl; @@ -1232,6 +1322,11 @@ attremptycheckend: } } + for_( it, _pimpl->_uncompiledPredicated.begin(), _pimpl->_uncompiledPredicated.end() ) + { + str << "complex: "<< it->serialize() << delim; + } + //separating delim - protection str << delim; }