libept
0.5.25
|
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