libept  0.5.25
debtags.h
Go to the documentation of this file.
00001 // -*- mode: c++; tab-width: 4; indent-tabs-mode: t -*-
00002 /* @file
00003  * @author Enrico Zini (enrico) <enrico@enricozini.org>
00004  */
00005 
00006 /*
00007  * libpkg Debtags data provider
00008  *
00009  * Copyright (C) 2003-2007  Enrico Zini <enrico@debian.org>
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024  */
00025 
00026 #ifndef EPT_DEBTAGS_DEBTAGS_H
00027 #define EPT_DEBTAGS_DEBTAGS_H
00028 
00029 #include <ept/debtags/tag.h>
00030 #include <ept/debtags/vocabulary.h>
00031 #include <ept/debtags/maint/pkgid.h>
00032 
00033 #include <tagcoll/coll/base.h>
00034 #include <tagcoll/coll/intdiskindex.h>
00035 #include <tagcoll/coll/patched.h>
00036 
00037 namespace ept {
00038 namespace debtags {
00039 class Debtags;
00040 }
00041 }
00042 
00043 namespace tagcoll {
00044 template< typename _, typename _1 > class PatchList;
00045 
00046 namespace coll {
00047 
00048 template<>
00049 struct coll_traits< ept::debtags::Debtags >
00050 {
00051     typedef std::string item_type;
00052     typedef ept::debtags::Tag tag_type;
00053     typedef std::set< ept::debtags::Tag > tagset_type;
00054     typedef std::set< std::string > itemset_type;
00055 };
00056 
00057 }
00058 }
00059 
00060 namespace ept {
00061 namespace debtags {
00062 
00075 class Debtags : public tagcoll::coll::Collection<Debtags>
00076 {
00077 protected:
00078     // Master mmap index container
00079     tagcoll::diskindex::MasterMMap mastermmap;
00080 
00081     // Debtags database
00082     tagcoll::coll::IntDiskIndex m_rocoll;
00083     tagcoll::coll::Patched< tagcoll::coll::IntDiskIndex > m_coll;
00084 
00085     // Package name to ID mapping
00086     PkgId m_pkgid;
00087 
00088     // Tag vocabulary
00089     Vocabulary m_voc;
00090 
00091     // User rc directory to store patches
00092     std::string rcdir;
00093 
00094     // Last modification timestamp of the index
00095     time_t m_timestamp;
00096 
00097     std::string packageByID(int id) const
00098     {
00099         return m_pkgid.byID(id);
00100     }
00101 
00102     template<typename IDS>
00103     std::set<std::string> packagesById(const IDS& ids) const
00104     {
00105         std::set<std::string> pkgs;
00106         for (typename IDS::const_iterator i = ids.begin();
00107                 i != ids.end(); ++i)
00108             pkgs.insert(packageByID(*i));
00109         return pkgs;
00110     }
00111 
00112     int idByPackage(const std::string& pkg) const
00113     {
00114         return m_pkgid.byName(pkg);
00115     }
00116 
00117     template<typename PKGS>
00118     std::set<int> idsByPackages(const PKGS& pkgs) const
00119     {
00120         std::set<int> ids;
00121         for (typename PKGS::const_iterator i = pkgs.begin();
00122                 i != pkgs.end(); ++i)
00123             ids.insert(idByPackage(*i));
00124         return ids;
00125     }
00126 
00127 public:
00128     typedef tagcoll::coll::Patched< tagcoll::coll::IntDiskIndex > coll_type;
00129     typedef std::pair< std::string, std::set<Tag> > value_type;
00130 
00131     class const_iterator
00132     {
00133         const Debtags& coll;
00134         Debtags::coll_type::const_iterator ci;
00135         mutable const Debtags::value_type* cached_val;
00136 
00137     protected:
00138         const_iterator(const Debtags& coll,
00139                         const Debtags::coll_type::const_iterator& ci)
00140             : coll(coll), ci(ci), cached_val(0) {}
00141 
00142     public:
00143         ~const_iterator()
00144         {
00145             if (cached_val)
00146                 delete cached_val;
00147         }
00148         const Debtags::value_type operator*() const
00149         {
00150             if (cached_val)
00151                 return *cached_val;
00152 
00153             return make_pair(coll.packageByID(ci->first), coll.vocabulary().tagsByID(ci->second));
00154         }
00155         const Debtags::value_type* operator->() const
00156         {
00157             if (cached_val)
00158                 return cached_val;
00159             return cached_val = new Debtags::value_type(*(*this));
00160         }
00161         const_iterator& operator++()
00162         {
00163             ++ci;
00164             if (cached_val)
00165             {
00166                 delete cached_val;
00167                 cached_val = 0;
00168             }
00169             return *this;
00170         }
00171         bool operator==(const const_iterator& iter) const
00172         {
00173             return ci == iter.ci;
00174         }
00175         bool operator!=(const const_iterator& iter) const
00176         {
00177             return ci != iter.ci;
00178         }
00179 
00180         friend class Debtags;
00181     };
00182     const_iterator begin() const { return const_iterator(*this, m_coll.begin()); }
00183     const_iterator end() const { return const_iterator(*this, m_coll.end()); }
00184 
00193     Debtags(bool editable = false);
00194     ~Debtags() {}
00195 
00197     time_t timestamp() const { return m_timestamp; }
00198 
00200     bool hasData() const { return m_timestamp != 0; }
00201 
00202     coll_type& tagdb() { return m_coll; }
00203     const coll_type& tagdb() const { return m_coll; }
00204     tagcoll::PatchList<std::string, Tag> changes() const;
00205 
00206 #if 0
00207     template<typename ITEMS, typename TAGS>
00208     void insert(const ITEMS& items, const TAGS& tags)
00209     {
00210         for (typename ITEMS::const_iterator i = items.begin();
00211                 i != items.end(); ++i)
00212             m_changes.addPatch(Patch(*i, tags, TagSet()));
00213     }
00214 
00215     template<typename ITEMS>
00216     void insert(const ITEMS& items, const wibble::Empty<Tag>& tags)
00217     {
00218         // Nothing to do in this case
00219     }
00220 
00224     const Patches& changes() const { return m_changes; }
00225 
00229     void resetChanges() { m_changes.clear(); }
00230 
00234     void setChanges(const Patches& changes);
00235 
00239     void addChanges(const Patches& changes);
00240 #endif
00241 
00242     bool hasTag(const Tag& tag) const { return m_coll.hasTag(tag.id()); }
00243 
00244     std::set<Tag> getTagsOfItem(const std::string& item) const
00245     {
00246         int id = idByPackage(item);
00247         if (id == -1) return std::set<Tag>();
00248         return vocabulary().tagsByID(m_coll.getTagsOfItem(id));
00249     }
00250 
00251     template<typename ITEMS>
00252     std::set<Tag> getTagsOfItems(const ITEMS& items) const
00253     {
00254         return vocabulary().tagsByID(m_coll.getTagsOfItems(idsByPackages(items)));
00255     }
00256 
00257     std::set<std::string> getItemsHavingTag(const Tag& tag) const
00258     {
00259         return packagesById(m_coll.getItemsHavingTag(tag.id()));
00260     }
00261     template<typename TAGS>
00262     std::set<std::string> getItemsHavingTags(const TAGS& tags) const
00263     {
00264         std::set<int> itags;
00265         for (typename TAGS::const_iterator i = tags.begin();
00266                 i != tags.end(); ++i)
00267             itags.insert(i->id());
00268         return packagesById(m_coll.getItemsHavingTags(itags));
00269     }
00270 
00271 #if 0
00272     ItemSet getTaggedItems() const;
00273 #endif
00274     std::set<Tag> getAllTags() const
00275     {
00276         return vocabulary().tagsByID(m_coll.getAllTags());
00277     }
00278 
00280     Vocabulary& vocabulary() { return m_voc; }
00282     const Vocabulary& vocabulary() const { return m_voc; }
00283 
00289     PkgId& pkgid() { return m_pkgid; }
00295     const PkgId& pkgid() const { return m_pkgid; }
00296 
00297     int getCardinality(const Tag& tag) const
00298     {
00299         return m_coll.getCardinality(tag.id());
00300     }
00301 
00302     void applyChange(const tagcoll::PatchList<std::string, Tag>& change)
00303     {
00304         using namespace tagcoll;
00305         PatchList<int, int> intp;
00306         for (PatchList<std::string, Tag>::const_iterator i = change.begin();
00307                 i != change.end(); ++i)
00308         {
00309             Patch<int, int> p(idByPackage(i->first));
00310             for (std::set<Tag>::const_iterator j = i->second.added.begin();
00311                     j != i->second.added.end(); ++j)
00312                 p.add(j->id());
00313             for (std::set<Tag>::const_iterator j = i->second.removed.begin();
00314                     j != i->second.removed.end(); ++j)
00315                 p.remove(j->id());
00316             intp.addPatch(p);
00317         }
00318         m_coll.applyChange(intp);
00319     }
00320 
00321 #if 0
00322     template<typename OUT>
00323     void output(OUT out) const
00324     {
00325         for (const_iterator i = begin(); i != end(); ++i)
00326         {
00327             *out = *i;
00328             ++out;
00329         }
00330     }
00331 #endif
00332 
00333 
00334 
00339     //static bool hasTagDatabase();
00340 
00341 
00346     void savePatch();
00347 
00352     void savePatch(const tagcoll::PatchList<std::string, std::string>& patch);
00353 
00358     void savePatch(const tagcoll::PatchList<std::string, Tag>& patch);
00359 
00364     void sendPatch();
00365 
00369     void sendPatch(const tagcoll::PatchList<std::string, std::string>& patch);
00370 
00374     void sendPatch(const tagcoll::PatchList<std::string, Tag>& patch);
00375 
00376 
00382     template<typename OUT>
00383     void outputSystem(const OUT& cons);
00384 
00390     template<typename OUT>
00391     void outputSystem(const std::string& filename, const OUT& out);
00392 
00399     template<typename OUT>
00400     void outputPatched(const OUT& cons);
00401 
00408     template<typename OUT>
00409     void outputPatched(const std::string& filename, const OUT& out);
00410 };
00411 
00412 
00413 }
00414 }
00415 
00416 // vim:set ts=4 sw=4:
00417 #endif