libept  0.5.25
debtags.h
Go to the documentation of this file.
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>
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;
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 
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
87 
88  // Tag vocabulary
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  std::string packageByID(int id) const
98  {
99  return m_pkgid.byID(id);
100  }
101 
102  template<typename IDS>
103  std::set<std::string> packagesById(const IDS& ids) const
104  {
105  std::set<std::string> pkgs;
106  for (typename IDS::const_iterator i = ids.begin();
107  i != ids.end(); ++i)
108  pkgs.insert(packageByID(*i));
109  return pkgs;
110  }
111 
112  int idByPackage(const std::string& pkg) const
113  {
114  return m_pkgid.byName(pkg);
115  }
116 
117  template<typename PKGS>
118  std::set<int> idsByPackages(const PKGS& pkgs) const
119  {
120  std::set<int> ids;
121  for (typename PKGS::const_iterator i = pkgs.begin();
122  i != pkgs.end(); ++i)
123  ids.insert(idByPackage(*i));
124  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 
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  const Debtags::coll_type::const_iterator& ci)
140  : coll(coll), ci(ci), cached_val(0) {}
141 
142  public:
144  {
145  if (cached_val)
146  delete cached_val;
147  }
149  {
150  if (cached_val)
151  return *cached_val;
152 
153  return make_pair(coll.packageByID(ci->first), coll.vocabulary().tagsByID(ci->second));
154  }
156  {
157  if (cached_val)
158  return cached_val;
159  return cached_val = new Debtags::value_type(*(*this));
160  }
162  {
163  ++ci;
164  if (cached_val)
165  {
166  delete cached_val;
167  cached_val = 0;
168  }
169  return *this;
170  }
171  bool operator==(const const_iterator& iter) const
172  {
173  return ci == iter.ci;
174  }
175  bool operator!=(const const_iterator& iter) const
176  {
177  return ci != iter.ci;
178  }
179 
180  friend class Debtags;
181  };
182  const_iterator begin() const { return const_iterator(*this, m_coll.begin()); }
183  const_iterator end() const { return const_iterator(*this, m_coll.end()); }
184 
193  Debtags(bool editable = false);
194  ~Debtags() {}
195 
197  time_t timestamp() const { return m_timestamp; }
198 
200  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 
224  const Patches& changes() const { return m_changes; }
225 
229  void resetChanges() { m_changes.clear(); }
230 
234  void setChanges(const Patches& changes);
235 
239  void addChanges(const Patches& changes);
240 #endif
241 
242  bool hasTag(const Tag& tag) const { return m_coll.hasTag(tag.id()); }
243 
244  std::set<Tag> getTagsOfItem(const std::string& item) const
245  {
246  int id = idByPackage(item);
247  if (id == -1) return std::set<Tag>();
248  return vocabulary().tagsByID(m_coll.getTagsOfItem(id));
249  }
250 
251  template<typename ITEMS>
252  std::set<Tag> getTagsOfItems(const ITEMS& items) const
253  {
254  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  std::set<std::string> getItemsHavingTags(const TAGS& tags) const
263  {
264  std::set<int> itags;
265  for (typename TAGS::const_iterator i = tags.begin();
266  i != tags.end(); ++i)
267  itags.insert(i->id());
268  return packagesById(m_coll.getItemsHavingTags(itags));
269  }
270 
271 #if 0
272  ItemSet getTaggedItems() const;
273 #endif
274  std::set<Tag> getAllTags() const
275  {
276  return vocabulary().tagsByID(m_coll.getAllTags());
277  }
278 
280  Vocabulary& vocabulary() { return m_voc; }
282  const Vocabulary& vocabulary() const { return m_voc; }
283 
289  PkgId& pkgid() { return m_pkgid; }
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  void applyChange(const tagcoll::PatchList<std::string, Tag>& change)
303  {
304  using namespace tagcoll;
305  PatchList<int, int> intp;
306  for (PatchList<std::string, Tag>::const_iterator i = change.begin();
307  i != change.end(); ++i)
308  {
309  Patch<int, int> p(idByPackage(i->first));
310  for (std::set<Tag>::const_iterator j = i->second.added.begin();
311  j != i->second.added.end(); ++j)
312  p.add(j->id());
313  for (std::set<Tag>::const_iterator j = i->second.removed.begin();
314  j != i->second.removed.end(); ++j)
315  p.remove(j->id());
316  intp.addPatch(p);
317  }
318  m_coll.applyChange(intp);
319  }
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 
339  //static bool hasTagDatabase();
340 
341 
346  void savePatch();
347 
352  void savePatch(const tagcoll::PatchList<std::string, std::string>& patch);
353 
358  void savePatch(const tagcoll::PatchList<std::string, Tag>& patch);
359 
364  void sendPatch();
365 
369  void sendPatch(const tagcoll::PatchList<std::string, std::string>& patch);
370 
374  void sendPatch(const tagcoll::PatchList<std::string, Tag>& patch);
375 
376 
382  template<typename OUT>
383  void outputSystem(const OUT& cons);
384 
390  template<typename OUT>
391  void outputSystem(const std::string& filename, const OUT& out);
392 
399  template<typename OUT>
400  void outputPatched(const OUT& cons);
401 
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