LCOV - lcov.info - ept/debtags/debtags.h

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