LTP GCOV extension - code coverage report
Current view: directory - ept/debtags - debtags.h
Test: lcov.info
Date: 2008-08-14 Instrumented lines: 72
Code covered: 93.1 % Executed lines: 67

       1                 : // -*- mode: c++; tab-width: 4; indent-tabs-mode: t -*-
       2                 : /* @file
       3                 :  * @author Enrico Zini (enrico) <enrico@enricozini.org>
       4                 :  */
       5                 : 
       6                 : /*
       7                 :  * libpkg Debtags data provider
       8                 :  *
       9                 :  * Copyright (C) 2003-2007  Enrico Zini <enrico@debian.org>
      10                 :  *
      11                 :  * This program is free software; you can redistribute it and/or modify
      12                 :  * it under the terms of the GNU General Public License as published by
      13                 :  * the Free Software Foundation; either version 2 of the License, or
      14                 :  * (at your option) any later version.
      15                 :  *
      16                 :  * This program is distributed in the hope that it will be useful,
      17                 :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :  * GNU General Public License for more details.
      20                 :  *
      21                 :  * You should have received a copy of the GNU General Public License
      22                 :  * along with this program; if not, write to the Free Software
      23                 :  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      24                 :  */
      25                 : 
      26                 : #ifndef EPT_DEBTAGS_DEBTAGS_H
      27                 : #define EPT_DEBTAGS_DEBTAGS_H
      28                 : 
      29                 : #include <ept/debtags/tag.h>
      30                 : #include <ept/debtags/vocabulary.h>
      31                 : #include <ept/debtags/maint/pkgid.h>
      32                 : 
      33                 : #include <tagcoll/coll/base.h>
      34                 : #include <tagcoll/coll/intdiskindex.h>
      35                 : #include <tagcoll/coll/patched.h>
      36                 : 
      37                 : namespace ept {
      38                 : namespace debtags {
      39                 : class Debtags;
      40                 : }
      41                 : }
      42                 : 
      43                 : namespace tagcoll {
      44                 : template< typename _, typename _1 > class PatchList;
      45                 : 
      46                 : namespace coll {
      47                 : 
      48                 : template<>
      49                 : struct coll_traits< ept::debtags::Debtags >
      50                 : {
      51                 :         typedef std::string item_type;
      52                 :         typedef ept::debtags::Tag tag_type;
      53                 :         typedef std::set< ept::debtags::Tag > tagset_type;
      54                 :         typedef std::set< std::string > itemset_type;
      55                 : };
      56                 : 
      57                 : }
      58                 : }
      59                 : 
      60                 : namespace ept {
      61                 : namespace debtags {
      62                 : 
      63                 : /**
      64                 :  * Access the on-disk Debtags tag database.
      65                 :  *
      66                 :  * The database is normally found in /var/lib/debtags.
      67                 :  *
      68                 :  * Tags and Facets are returned as Tag and Facet objects.  The objects follow
      69                 :  * the flyweight pattern and access the data contained in the Vocabulary
      70                 :  * instantiated inside Debtags.
      71                 :  *
      72                 :  * It is possible to get a reference to the Vocabulary object using the
      73                 :  * vocabulary() method.
      74                 :  */
      75                 : class Debtags : public tagcoll::coll::Collection<Debtags>
      76                 : {
      77                 : protected:
      78                 :         // Master mmap index container
      79                 :         tagcoll::diskindex::MasterMMap mastermmap;
      80                 : 
      81                 :         // Debtags database
      82                 :         tagcoll::coll::IntDiskIndex m_rocoll;
      83                 :         tagcoll::coll::Patched< tagcoll::coll::IntDiskIndex > m_coll;
      84                 : 
      85                 :         // Package name to ID mapping
      86                 :         PkgId m_pkgid;
      87                 : 
      88                 :         // Tag vocabulary
      89                 :         Vocabulary m_voc;
      90                 : 
      91                 :         // User rc directory to store patches
      92                 :         std::string rcdir;
      93                 : 
      94                 :         // Last modification timestamp of the index
      95                 :         time_t m_timestamp;
      96                 : 
      97           84710 :         std::string packageByID(int id) const
      98                 :         {
      99           84710 :                 return m_pkgid.byID(id);
     100                 :         }
     101                 : 
     102                 :         template<typename IDS>
     103               2 :         std::set<std::string> packagesById(const IDS& ids) const
     104                 :         {
     105               2 :                 std::set<std::string> pkgs;
     106             130 :                 for (typename IDS::const_iterator i = ids.begin();
     107                 :                                 i != ids.end(); ++i)
     108             128 :                         pkgs.insert(packageByID(*i));
     109               0 :                 return pkgs;
     110                 :         }
     111                 : 
     112               8 :         int idByPackage(const std::string& pkg) const
     113                 :         {
     114               8 :                 return m_pkgid.byName(pkg);
     115                 :         }
     116                 : 
     117                 :         template<typename PKGS>
     118               1 :         std::set<int> idsByPackages(const PKGS& pkgs) const
     119                 :         {
     120               1 :                 std::set<int> ids;
     121               2 :                 for (typename PKGS::const_iterator i = pkgs.begin();
     122                 :                                 i != pkgs.end(); ++i)
     123               1 :                         ids.insert(idByPackage(*i));
     124               0 :                 return ids;
     125                 :         }
     126                 : 
     127                 : public:
     128                 :         typedef tagcoll::coll::Patched< tagcoll::coll::IntDiskIndex > coll_type;
     129                 :         typedef std::pair< std::string, std::set<Tag> > value_type;
     130                 : 
     131                 :         class const_iterator
     132                 :         {
     133                 :                 const Debtags& coll;
     134                 :                 Debtags::coll_type::const_iterator ci;
     135                 :                 mutable const Debtags::value_type* cached_val;
     136                 : 
     137                 :         protected:
     138                 :                 const_iterator(const Debtags& coll,
     139           63443 :                                                 const Debtags::coll_type::const_iterator& ci)
     140           63443 :                         : coll(coll), ci(ci), cached_val(0) {}
     141                 : 
     142                 :         public:
     143           63443 :                 ~const_iterator()
     144                 :                 {
     145           63443 :                         if (cached_val)
     146               0 :                                 delete cached_val;
     147           63443 :                 }
     148           84580 :                 const Debtags::value_type operator*() const
     149                 :                 {
     150           84580 :                         if (cached_val)
     151               0 :                                 return *cached_val;
     152                 : 
     153           84580 :                         return make_pair(coll.packageByID(ci->first), coll.vocabulary().tagsByID(ci->second));
     154                 :                 }
     155          105725 :                 const Debtags::value_type* operator->() const
     156                 :                 {
     157          105725 :                         if (cached_val)
     158           42290 :                                 return cached_val;
     159           63435 :                         return cached_val = new Debtags::value_type(*(*this));
     160                 :                 }
     161           63435 :                 const_iterator& operator++()
     162                 :                 {
     163           63435 :                         ++ci;
     164           63435 :                         if (cached_val)
     165                 :                         {
     166           63435 :                                 delete cached_val;
     167           63435 :                                 cached_val = 0;
     168                 :                         }
     169           63435 :                         return *this;
     170                 :                 }
     171               1 :                 bool operator==(const const_iterator& iter) const
     172                 :                 {
     173               1 :                         return ci == iter.ci;
     174                 :                 }
     175           63438 :                 bool operator!=(const const_iterator& iter) const
     176                 :                 {
     177           63438 :                         return ci != iter.ci;
     178                 :                 }
     179                 : 
     180                 :                 friend class Debtags;
     181                 :         };
     182               4 :         const_iterator begin() const { return const_iterator(*this, m_coll.begin()); }
     183           63439 :         const_iterator end() const { return const_iterator(*this, m_coll.end()); }
     184                 : 
     185                 :         /**
     186                 :          * Create a new accessor for the on-disk Debtags database
     187                 :          *
     188                 :          * \param editable
     189                 :          * Specifies if recording of modifications should be enabled.  If editable
     190                 :          * is true, then the local state directory will be created when the object
     191                 :          * is instantiated.
     192                 :          */
     193                 :     Debtags(bool editable = false);
     194              10 :     ~Debtags() {}
     195                 : 
     196                 :         /// Get the timestamp of when the index was last updated
     197               1 :         time_t timestamp() const { return m_timestamp; }
     198                 : 
     199                 :         /// Return true if this data source has data, false if it's empty
     200               1 :         bool hasData() const { return m_timestamp != 0; }
     201                 : 
     202                 :         coll_type& tagdb() { return m_coll; }
     203                 :         const coll_type& tagdb() const { return m_coll; }
     204                 :         tagcoll::PatchList<std::string, Tag> changes() const;
     205                 : 
     206                 : #if 0
     207                 :         template<typename ITEMS, typename TAGS>
     208                 :         void insert(const ITEMS& items, const TAGS& tags)
     209                 :         {
     210                 :                 for (typename ITEMS::const_iterator i = items.begin();
     211                 :                                 i != items.end(); ++i)
     212                 :                         m_changes.addPatch(Patch(*i, tags, TagSet()));
     213                 :         }
     214                 : 
     215                 :         template<typename ITEMS>
     216                 :         void insert(const ITEMS& items, const wibble::Empty<Tag>& tags)
     217                 :         {
     218                 :                 // Nothing to do in this case
     219                 :         }
     220                 : 
     221                 :         /**
     222                 :          * Get the changes that have been applied to this collection
     223                 :          */
     224                 :         const Patches& changes() const { return m_changes; }
     225                 : 
     226                 :         /**
     227                 :          * Throw away all changes previously applied to this collection
     228                 :          */
     229                 :         void resetChanges() { m_changes.clear(); }
     230                 : 
     231                 :         /**
     232                 :          * Set the changes list to a specific patch list
     233                 :          */
     234                 :         void setChanges(const Patches& changes);
     235                 : 
     236                 :         /**
     237                 :          * Add a specific patch list to the changes list
     238                 :          */
     239                 :         void addChanges(const Patches& changes);
     240                 : #endif
     241                 : 
     242                 :     bool hasTag(const Tag& tag) const { return m_coll.hasTag(tag.id()); }
     243                 : 
     244               5 :         std::set<Tag> getTagsOfItem(const std::string& item) const
     245                 :         {
     246               5 :                 int id = idByPackage(item);
     247               5 :                 if (id == -1) return std::set<Tag>();
     248               4 :                 return vocabulary().tagsByID(m_coll.getTagsOfItem(id));
     249                 :         }
     250                 : 
     251                 :         template<typename ITEMS>
     252               1 :         std::set<Tag> getTagsOfItems(const ITEMS& items) const
     253                 :         {
     254               1 :                 return vocabulary().tagsByID(m_coll.getTagsOfItems(idsByPackages(items)));
     255                 :         }
     256                 : 
     257                 :         std::set<std::string> getItemsHavingTag(const Tag& tag) const
     258                 :         {
     259                 :                 return packagesById(m_coll.getItemsHavingTag(tag.id()));
     260                 :         }
     261                 :         template<typename TAGS>
     262               2 :         std::set<std::string> getItemsHavingTags(const TAGS& tags) const
     263                 :         {
     264               2 :                 std::set<int> itags;
     265              11 :                 for (typename TAGS::const_iterator i = tags.begin();
     266                 :                                 i != tags.end(); ++i)
     267               9 :                         itags.insert(i->id());
     268               2 :                 return packagesById(m_coll.getItemsHavingTags(itags));
     269                 :         }
     270                 : 
     271                 : #if 0
     272                 :         ItemSet getTaggedItems() const;
     273                 : #endif
     274               1 :         std::set<Tag> getAllTags() const
     275                 :         {
     276               1 :                 return vocabulary().tagsByID(m_coll.getAllTags());
     277                 :         }
     278                 : 
     279                 :         /// Access the vocabulary in use
     280              27 :     Vocabulary& vocabulary() { return m_voc; }
     281                 :         /// Access the vocabulary in use
     282           84590 :     const Vocabulary& vocabulary() const { return m_voc; }
     283                 : 
     284                 :         /**
     285                 :          * Access the PkgId in use.
     286                 :          *
     287                 :          * \note Future implementations may not rely on a PkgId
     288                 :          */
     289               4 :         PkgId& pkgid() { return m_pkgid; }
     290                 :         /**
     291                 :          * Access the PkgId in use.
     292                 :          *
     293                 :          * \note Future implementations may not rely on a PkgId
     294                 :          */
     295                 :         const PkgId& pkgid() const { return m_pkgid; }
     296                 : 
     297                 :         int getCardinality(const Tag& tag) const
     298                 :         {
     299                 :                 return m_coll.getCardinality(tag.id());
     300                 :         }
     301                 : 
     302               2 :         void applyChange(const tagcoll::PatchList<std::string, Tag>& change)
     303                 :         {
     304                 :                 using namespace tagcoll;
     305               2 :                 PatchList<int, int> intp;
     306               4 :                 for (PatchList<std::string, Tag>::const_iterator i = change.begin();
     307                 :                                 i != change.end(); ++i)
     308                 :                 {
     309               2 :                         Patch<int, int> p(idByPackage(i->first));
     310               4 :                         for (std::set<Tag>::const_iterator j = i->second.added.begin();
     311                 :                                         j != i->second.added.end(); ++j)
     312               2 :                                 p.add(j->id());
     313               2 :                         for (std::set<Tag>::const_iterator j = i->second.removed.begin();
     314                 :                                         j != i->second.removed.end(); ++j)
     315               0 :                                 p.remove(j->id());
     316               2 :                         intp.addPatch(p);
     317                 :                 }
     318               2 :                 m_coll.applyChange(intp);
     319               2 :         }
     320                 : 
     321                 : #if 0
     322                 :         template<typename OUT>
     323                 :         void output(OUT out) const
     324                 :         {
     325                 :                 for (const_iterator i = begin(); i != end(); ++i)
     326                 :                 {
     327                 :                         *out = *i;
     328                 :                         ++out;
     329                 :                 }
     330                 :         }
     331                 : #endif
     332                 : 
     333                 : 
     334                 : 
     335                 :         /**
     336                 :          * Check if the tag database has been created (i.e. if something
     337                 :          * equivalend to debtags update has been run)
     338                 :          */
     339                 :         //static bool hasTagDatabase();
     340                 : 
     341                 : 
     342                 :         /**
     343                 :          * Save in the state storage directory a patch that can be used to turn
     344                 :          * the system database into the collection given
     345                 :          */
     346                 :         void savePatch();
     347                 : 
     348                 :         /**
     349                 :          * Save in the state storage directory a patch to turn the system database
     350                 :          * into the collection given
     351                 :          */
     352                 :         void savePatch(const tagcoll::PatchList<std::string, std::string>& patch);
     353                 : 
     354                 :         /**
     355                 :          * Save in the state storage directory a patch to turn the system database
     356                 :          * into the collection given
     357                 :          */
     358                 :         void savePatch(const tagcoll::PatchList<std::string, Tag>& patch);
     359                 : 
     360                 :         /**
     361                 :          * Send to the central archive a patch that can be used to turn
     362                 :          * the system database into the collection given
     363                 :          */
     364                 :         void sendPatch();
     365                 : 
     366                 :         /**
     367                 :          * Send the given patch to the central archive
     368                 :          */
     369                 :         void sendPatch(const tagcoll::PatchList<std::string, std::string>& patch);
     370                 : 
     371                 :         /**
     372                 :          * Send the given patch to the central archive
     373                 :          */
     374                 :         void sendPatch(const tagcoll::PatchList<std::string, Tag>& patch);
     375                 : 
     376                 : 
     377                 :         /**
     378                 :          * Output the current Debian tags database to a consumer of <std::string, Tag>
     379                 :          *
     380                 :          * \note The collection is sent to 'cons' without merging repeated items
     381                 :          */
     382                 :         template<typename OUT>
     383               2 :         void outputSystem(const OUT& cons);
     384                 : 
     385                 :         /**
     386                 :          * Output the given tag file to a consumer of <std::string, Tag>
     387                 :          *
     388                 :          * \note The collection is sent to 'cons' without merging repeated items
     389                 :          */
     390                 :         template<typename OUT>
     391                 :         void outputSystem(const std::string& filename, const OUT& out);
     392                 : 
     393                 :         /**
     394                 :          * Output the current Debian tags database, patched with local patch,
     395                 :          * to a Consumer of <std::string, Tag>
     396                 :          *
     397                 :          * \note The collection is sent to 'cons' without merging repeated items
     398                 :          */
     399                 :         template<typename OUT>
     400               2 :         void outputPatched(const OUT& cons);
     401                 : 
     402                 :         /**
     403                 :          * Output the given tag file, patched with local patch,
     404                 :          * to a Consumer of <std::string, Tag>
     405                 :          *
     406                 :          * \note The collection is sent to 'cons' without merging repeated items
     407                 :          */
     408                 :         template<typename OUT>
     409                 :         void outputPatched(const std::string& filename, const OUT& out);
     410                 : };
     411                 : 
     412                 : 
     413                 : }
     414                 : }
     415                 : 
     416                 : // vim:set ts=4 sw=4:
     417                 : #endif

Generated by: LTP GCOV extension version 1.6