Mailinglist Archive: zypp-devel (227 mails)

< Previous Next >
Re: [zypp-devel] implementing PoolQuery iterator using sat-solver's Dataiterator
  • From: Josef Reidinger <jreidinger@xxxxxxx>
  • Date: Thu, 03 Apr 2008 13:49:54 +0200
  • Message-id: <47F4C462.5010906@xxxxxxx>
Jan Kupec wrote:
I have the following experimental PoolQuery::ResultIterator

extern "C"
{
#include "satsolver/repo.h";
}

class PoolQuery
{
public:

typedef ::_Dataiterator RepoDataIterator;

class ResultIterator : public boost::iterator_adaptor<
ResultIterator // Derived
, RepoDataIterator * // Base
, const sat::Solvable // Value
, boost::forward_traversal_tag // CategoryOrTraversal
, const sat::Solvable & // Reference
>

I think that have query tight linked to result of some repo search is not good idea, because it prevent some optimalization (like now if someone want query on name and kind f.e. thunar and patch - you must search thrue all repository with this, but you can use name index on pool and have it significantly fast).
So I think better is use own storage for results (so you shade how you implement query search) and iterate over it.


{
public:
ResultIterator()
: ResultIterator::iterator_adaptor_(0)
{ _rdit = 0; base_reference() = 0; }

ResultIterator(RepoDataIterator * rdit)
: ResultIterator::iterator_adaptor_(0)
{ _rdit = rdit; base_reference() = rdit; }

private:
friend class boost::iterator_core_access;

sat::Solvable dereference() const
{
return _rdit ? sat::Solvable(_rdit->solvid) :
sat::Solvable::noSolvable;
}

void increment()
{
if (::dataiterator_step(_rdit))
else
{
base_reference() = 0;
}
}

template <class OtherDerived, class OtherIterator, class V, class
C, class R, class D>
bool equal( const boost::iterator_adaptor<OtherDerived,
OtherIterator, V, C, R, D> & rhs ) const;
{
if (!rhs.base() && !base())
return true;
if (!rhs.base() || !base())
return false;
// quite useless since base() == rhs.base() always except for
// end()
if (rhs.base()->solvid == base()->solvid)
return true;
return false;
}

private:
RepoDataIterator * _rdit;
};

// PoolQuery methods&members go here....
}

I use (maybe wrongly) the RepoDataIterator * as the base.
RepoDataIterator is being created in PoolQuery::Impl, the begin() and
end() methods look like this:

PoolQuery::ResultIterator PoolQuery::Impl::begin()
{
sat::Pool pool(sat::Pool::instance());
sat::Pool::RepositoryIterator itr = pool.reposBegin();
::dataiterator_init(&_rdit, itr->get(), 0 /*p*/, 0/*keyname*/, 0
/*matchstring*/, _flags);
INT << "next: " << ::dataiterator_step(&_rdit) << endl;
return PoolQuery::ResultIterator(&_rdit);
}

Little performance note - if you add flag dirty which is set to true everytime you change query settings and recreate result only if is set, then you can save some searching (for example if someone want two time iterate over same results).


PoolQuery::ResultIterator PoolQuery::Impl::end()
{
return PoolQuery::ResultIterator(0);
}


This has (at least :O) two drawbacks:

1) RepoDataIterator * is the same in all instances except for those
created with PoolQuery::end()

if I understand it, own storage can help with this problem.

2) PoolQuery::begin() always resets the dataiterator state for all
existing instances


If used dirty flag, iterator is invalidate only when you change query settings.
If you don't want invalidate iterator you must have some iterator with reference counting pointer to old storage and always create dynamically new.

This is probably a really bad evil. Can somebody (ma? :O) give me a
pointer how to do it better? I would very much love to discover the
world by myself, but the time is unfortunately running out :O(

Please ignore the fact that this does not iterate across repositories
for now; and that it iterates through solvable attributes, not just the
solvables.

cheers,

jano

--
To unsubscribe, e-mail: zypp-devel+unsubscribe@xxxxxxxxxxxx
For additional commands, e-mail: zypp-devel+help@xxxxxxxxxxxx

< Previous Next >
References