satsolver  0.17.2
poolid.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007, Novell Inc.
3  *
4  * This program is licensed under the BSD license, read LICENSE.BSD
5  * for further information
6  */
7 
8 /*
9  * poolid.c
10  *
11  * Id management
12  */
13 
14 #include <stdlib.h>
15 #include <string.h>
16 #include <stdio.h>
17 
18 #include "pool.h"
19 #include "poolid.h"
20 #include "poolid_private.h"
21 #include "util.h"
22 
23 
24 /* intern string into pool, return id */
25 
26 Id
27 pool_str2id(Pool *pool, const char *str, int create)
28 {
29  int oldnstrings = pool->ss.nstrings;
30  Id id = stringpool_str2id(&pool->ss, str, create);
31  if (create && pool->whatprovides && oldnstrings != pool->ss.nstrings && (id & WHATPROVIDES_BLOCK) == 0)
32  {
33  /* grow whatprovides array */
34  pool->whatprovides = sat_realloc(pool->whatprovides, (id + (WHATPROVIDES_BLOCK + 1)) * sizeof(Offset));
35  memset(pool->whatprovides + id, 0, (WHATPROVIDES_BLOCK + 1) * sizeof(Offset));
36  }
37  return id;
38 }
39 
40 Id
41 pool_strn2id(Pool *pool, const char *str, unsigned int len, int create)
42 {
43  int oldnstrings = pool->ss.nstrings;
44  Id id = stringpool_strn2id(&pool->ss, str, len, create);
45  if (create && pool->whatprovides && oldnstrings != pool->ss.nstrings && (id & WHATPROVIDES_BLOCK) == 0)
46  {
47  /* grow whatprovides array */
48  pool->whatprovides = sat_realloc(pool->whatprovides, (id + (WHATPROVIDES_BLOCK + 1)) * sizeof(Offset));
49  memset(pool->whatprovides + id, 0, (WHATPROVIDES_BLOCK + 1) * sizeof(Offset));
50  }
51  return id;
52 }
53 
54 Id
55 pool_rel2id(Pool *pool, Id name, Id evr, int flags, int create)
56 {
57  Hashval h;
58  unsigned int hh;
59  Hashmask hashmask;
60  int i;
61  Id id;
62  Hashtable hashtbl;
63  Reldep *ran;
64 
65  hashmask = pool->relhashmask;
66  hashtbl = pool->relhashtbl;
67  ran = pool->rels;
68 
69  /* extend hashtable if needed */
70  if (pool->nrels * 2 > hashmask)
71  {
72  sat_free(pool->relhashtbl);
73  pool->relhashmask = hashmask = mkmask(pool->nrels + REL_BLOCK);
74  pool->relhashtbl = hashtbl = sat_calloc(hashmask + 1, sizeof(Id));
75  // rehash all rels into new hashtable
76  for (i = 1; i < pool->nrels; i++)
77  {
78  h = relhash(ran[i].name, ran[i].evr, ran[i].flags) & hashmask;
79  hh = HASHCHAIN_START;
80  while (hashtbl[h])
81  h = HASHCHAIN_NEXT(h, hh, hashmask);
82  hashtbl[h] = i;
83  }
84  }
85 
86  /* compute hash and check for match */
87  h = relhash(name, evr, flags) & hashmask;
88  hh = HASHCHAIN_START;
89  while ((id = hashtbl[h]) != 0)
90  {
91  if (ran[id].name == name && ran[id].evr == evr && ran[id].flags == flags)
92  break;
93  h = HASHCHAIN_NEXT(h, hh, hashmask);
94  }
95  if (id)
96  return MAKERELDEP(id);
97 
98  if (!create)
99  return ID_NULL;
100 
101  id = pool->nrels++;
102  /* extend rel space if needed */
103  pool->rels = sat_extend(pool->rels, id, 1, sizeof(Reldep), REL_BLOCK);
104  hashtbl[h] = id;
105  ran = pool->rels + id;
106  ran->name = name;
107  ran->evr = evr;
108  ran->flags = flags;
109 
110  /* extend whatprovides_rel if needed */
111  if (pool->whatprovides_rel && (id & WHATPROVIDES_BLOCK) == 0)
112  {
113  pool->whatprovides_rel = sat_realloc2(pool->whatprovides_rel, id + (WHATPROVIDES_BLOCK + 1), sizeof(Offset));
114  memset(pool->whatprovides_rel + id, 0, (WHATPROVIDES_BLOCK + 1) * sizeof(Offset));
115  }
116  return MAKERELDEP(id);
117 }
118 
119 
120 // Id -> String
121 // for rels (returns name only) and strings
122 //
123 const char *
124 pool_id2str(const Pool *pool, Id id)
125 {
126  if (ISRELDEP(id))
127  {
128  Reldep *rd = GETRELDEP(pool, id);
129  if (ISRELDEP(rd->name))
130  return "REL";
131  return pool->ss.stringspace + pool->ss.strings[rd->name];
132  }
133  return pool->ss.stringspace + pool->ss.strings[id];
134 }
135 
136 static const char *rels[] = {
137  " ! ",
138 #ifndef DEBIAN_SEMANTICS
139  " > ",
140 #else
141  " >> ",
142 #endif
143  " = ",
144  " >= ",
145 #ifndef DEBIAN_SEMANTICS
146  " < ",
147 #else
148  " << ",
149 #endif
150  " <> ",
151  " <= ",
152  " <=> "
153 };
154 
155 
156 // get operator for RelId
157 const char *
158 pool_id2rel(const Pool *pool, Id id)
159 {
160  Reldep *rd;
161  if (!ISRELDEP(id))
162  return "";
163  rd = GETRELDEP(pool, id);
164  switch (rd->flags)
165  {
166  case 0: case 1: case 2: case 3:
167  case 4: case 5: case 6: case 7:
168  return rels[rd->flags & 7];
169  case REL_AND:
170  return " & ";
171  case REL_OR:
172  return " | ";
173  case REL_WITH:
174  return " + ";
175  case REL_NAMESPACE:
176  return " NAMESPACE "; /* actually not used in dep2str */
177  case REL_ARCH:
178  return ".";
179  case REL_FILECONFLICT:
180  return " FILECONFLICT ";
181  default:
182  break;
183  }
184  return " ??? ";
185 }
186 
187 
188 // get e:v.r for Id
189 //
190 const char *
191 pool_id2evr(const Pool *pool, Id id)
192 {
193  Reldep *rd;
194  if (!ISRELDEP(id))
195  return "";
196  rd = GETRELDEP(pool, id);
197  if (ISRELDEP(rd->evr))
198  return "(REL)";
199  return pool->ss.stringspace + pool->ss.strings[rd->evr];
200 }
201 
202 static int
203 dep2strlen(const Pool *pool, Id id)
204 {
205  int l = 0;
206 
207  while (ISRELDEP(id))
208  {
209  Reldep *rd = GETRELDEP(pool, id);
210  /* add 2 for parens */
211  l += 2 + dep2strlen(pool, rd->name) + strlen(id2rel(pool, id));
212  id = rd->evr;
213  }
214  return l + strlen(pool->ss.stringspace + pool->ss.strings[id]);
215 }
216 
217 static void
218 dep2strcpy(const Pool *pool, char *p, Id id, int oldrel)
219 {
220  while (ISRELDEP(id))
221  {
222  Reldep *rd = GETRELDEP(pool, id);
223  if (oldrel == REL_AND || oldrel == REL_OR || oldrel == REL_WITH)
224  if (rd->flags == REL_AND || rd->flags == REL_OR || rd->flags == REL_WITH)
225  if (oldrel != rd->flags)
226  {
227  *p++ = '(';
228  dep2strcpy(pool, p, rd->name, rd->flags);
229  p += strlen(p);
230  strcpy(p, id2rel(pool, id));
231  p += strlen(p);
232  dep2strcpy(pool, p, rd->evr, rd->flags);
233  strcat(p, ")");
234  return;
235  }
236  dep2strcpy(pool, p, rd->name, rd->flags);
237  p += strlen(p);
238  if (rd->flags == REL_NAMESPACE)
239  {
240  *p++ = '(';
241  dep2strcpy(pool, p, rd->evr, rd->flags);
242  strcat(p, ")");
243  return;
244  }
245  if (rd->flags == REL_FILECONFLICT)
246  {
247  *p = 0;
248  return;
249  }
250  strcpy(p, id2rel(pool, id));
251  p += strlen(p);
252  id = rd->evr;
253  oldrel = rd->flags;
254  }
255  strcpy(p, pool->ss.stringspace + pool->ss.strings[id]);
256 }
257 
258 const char *
259 pool_dep2str(Pool *pool, Id id)
260 {
261  char *p;
262  if (!ISRELDEP(id))
263  return pool->ss.stringspace + pool->ss.strings[id];
264  p = pool_alloctmpspace(pool, dep2strlen(pool, id) + 1);
265  dep2strcpy(pool, p, id, 0);
266  return p;
267 }
268 
269 void
271 {
272  stringpool_shrink(&pool->ss);
273 }
274 
275 void
277 {
278  pool->rels = sat_extend_resize(pool->rels, pool->nrels, sizeof(Reldep), REL_BLOCK);
279 }
280 
281 // reset all hash tables
282 //
283 void
285 {
286  stringpool_freehash(&pool->ss);
287  pool->relhashtbl = sat_free(pool->relhashtbl);
288  pool->relhashmask = 0;
289 }
290 
291 // EOF