static Hashtable
joinhash_init(Repo *repo, Hashval *hmp)
{
  Hashval hm = mkmask(repo->nsolvables);
  Hashtable ht = solv_calloc(hm + 1, sizeof(*ht));
  Hashval h, hh;
  Solvable *s;
  int i;

  FOR_REPO_SOLVABLES(repo, i, s)
    {
      hh = HASHCHAIN_START;
      h = s->name & hm;
      while (ht[h])
        h = HASHCHAIN_NEXT(h, hh, hm);
      ht[h] = i;
    }
Example #2
0
Id
pool_rel2id(Pool *pool, Id name, Id evr, int flags, int create)
{
  Hashval h, hh, hashmask;
  int i;
  Id id;
  Hashtable hashtbl;
  Reldep *ran;

  hashmask = pool->relhashmask;
  hashtbl = pool->relhashtbl;
  ran = pool->rels;
  
  /* extend hashtable if needed */
  if (pool->nrels * 2 > hashmask)
    {
      solv_free(pool->relhashtbl);
      pool->relhashmask = hashmask = mkmask(pool->nrels + REL_BLOCK);
      pool->relhashtbl = hashtbl = solv_calloc(hashmask + 1, sizeof(Id));
      /* rehash all rels into new hashtable */
      for (i = 1; i < pool->nrels; i++)
	{
	  h = relhash(ran[i].name, ran[i].evr, ran[i].flags) & hashmask;
	  hh = HASHCHAIN_START;
	  while (hashtbl[h])
	    h = HASHCHAIN_NEXT(h, hh, hashmask);
	  hashtbl[h] = i;
	}
    }
  
  /* compute hash and check for match */
  h = relhash(name, evr, flags) & hashmask;
  hh = HASHCHAIN_START;
  while ((id = hashtbl[h]) != 0)
    {
      if (ran[id].name == name && ran[id].evr == evr && ran[id].flags == flags)
	break;
      h = HASHCHAIN_NEXT(h, hh, hashmask);
    }
  if (id)
    return MAKERELDEP(id);

  if (!create)
    return ID_NULL;

  id = pool->nrels++;
  /* extend rel space if needed */
  pool->rels = solv_extend(pool->rels, id, 1, sizeof(Reldep), REL_BLOCK);
  hashtbl[h] = id;
  ran = pool->rels + id;
  ran->name = name;
  ran->evr = evr;
  ran->flags = flags;

  /* extend whatprovides_rel if needed */
  if (pool->whatprovides_rel && (id & WHATPROVIDES_BLOCK) == 0)
    {
      pool->whatprovides_rel = solv_realloc2(pool->whatprovides_rel, id + (WHATPROVIDES_BLOCK + 1), sizeof(Offset));
      memset(pool->whatprovides_rel + id, 0, (WHATPROVIDES_BLOCK + 1) * sizeof(Offset));
    }
  return MAKERELDEP(id);
}
Example #3
0
/* 
 * Optimization for packages with an excessive amount of provides/requires:
 * if the number of deps exceed a threshold, we build a hash of the already
 * seen ids.
 */
static Offset
repo_addid_dep_hash(Repo *repo, Offset olddeps, Id id, Id marker, int size)
{
  Id oid, *oidp;
  int before;
  Hashval h, hh;
  Id hid;

  before = 0;
  if (marker)
    {
      if (marker < 0)
	{
	  marker = -marker;
	  before = 1;
	}
      if (marker == id)
	marker = 0;
    }

  /* maintain hash and lastmarkerpos */
  if (repo->lastidhash_idarraysize != repo->idarraysize || size * 2 > repo->lastidhash_mask || repo->lastmarker != marker)
    {
      repo->lastmarkerpos = 0;
      if (size * 2 > repo->lastidhash_mask)
	{
	  repo->lastidhash_mask = mkmask(size < REPO_ADDID_DEP_HASHMIN ? REPO_ADDID_DEP_HASHMIN : size);
	  repo->lastidhash = solv_realloc2(repo->lastidhash, repo->lastidhash_mask + 1, sizeof(Id));
	}
      memset(repo->lastidhash, 0, (repo->lastidhash_mask + 1) * sizeof(Id));
      for (oidp = repo->idarraydata + olddeps; (oid = *oidp) != 0; oidp++)
	{
	  h = oid & repo->lastidhash_mask;
	  hh = HASHCHAIN_START;
	  while (repo->lastidhash[h] != 0)
	    h = HASHCHAIN_NEXT(h, hh, repo->lastidhash_mask);
	  repo->lastidhash[h] = oid;
	  if (marker && oid == marker)
	    repo->lastmarkerpos = oidp - repo->idarraydata;
	}
      repo->lastmarker = marker;
      repo->lastidhash_idarraysize = repo->idarraysize;
    }

  /* check the hash! */
  h = id & repo->lastidhash_mask;
  hh = HASHCHAIN_START;
  while ((hid = repo->lastidhash[h]) != 0 && hid != id)
    h = HASHCHAIN_NEXT(h, hh, repo->lastidhash_mask);
  /* put new element in hash */
  if (!hid)
    repo->lastidhash[h] = id;
  else if (marker == SOLVABLE_FILEMARKER && (!before || !repo->lastmarkerpos))
    return olddeps;
  if (marker && !before && !repo->lastmarkerpos)
    {
      /* we have to add the marker first */
      repo->lastmarkerpos = repo->idarraysize - 1;
      olddeps = repo_addid(repo, olddeps, marker);
      /* now put marker in hash */
      h = marker & repo->lastidhash_mask;
      hh = HASHCHAIN_START;
      while (repo->lastidhash[h] != 0)
	h = HASHCHAIN_NEXT(h, hh, repo->lastidhash_mask);
      repo->lastidhash[h] = marker;
      repo->lastidhash_idarraysize = repo->idarraysize;
    }
  if (!hid)
    {
      /* new entry, insert in correct position */
      if (marker && before && repo->lastmarkerpos)
	{
	  /* need to add it before the marker */
	  olddeps = repo_addid(repo, olddeps, id);	/* dummy to make room */
	  memmove(repo->idarraydata + repo->lastmarkerpos + 1, repo->idarraydata + repo->lastmarkerpos, (repo->idarraysize - repo->lastmarkerpos - 2) * sizeof(Id));
	  repo->idarraydata[repo->lastmarkerpos++] = id;
	}
      else
	{
	  /* just append it to the end */
	  olddeps = repo_addid(repo, olddeps, id);
	}
      repo->lastidhash_idarraysize = repo->idarraysize;
      return olddeps;
    }
  /* we already have it in the hash */
  if (!marker)
    return olddeps;
  if (marker == SOLVABLE_FILEMARKER)
    {
      /* check if it is in the wrong half */
      /* (we already made sure that "before" and "lastmarkerpos" are set, see above) */
      for (oidp = repo->idarraydata + repo->lastmarkerpos + 1; (oid = *oidp) != 0; oidp++)
	if (oid == id)
	  break;
      if (!oid)
	return olddeps;
      /* yes, wrong half. copy it over */
      memmove(repo->idarraydata + repo->lastmarkerpos + 1, repo->idarraydata + repo->lastmarkerpos, (oidp - (repo->idarraydata + repo->lastmarkerpos)) * sizeof(Id));
      repo->idarraydata[repo->lastmarkerpos++] = id;
      return olddeps;
    }
  if (before)
    return olddeps;
  /* check if it is in the correct half */
  for (oidp = repo->idarraydata + repo->lastmarkerpos + 1; (oid = *oidp) != 0; oidp++)
    if (oid == id)
      return olddeps;
  /* nope, copy it over */
  for (oidp = repo->idarraydata + olddeps; (oid = *oidp) != 0; oidp++)
    if (oid == id)
      break;
  if (!oid)
    return olddeps;	/* should not happen */
  memmove(oidp, oidp + 1, (repo->idarraydata + repo->idarraysize - oidp - 2) * sizeof(Id));
  repo->idarraydata[repo->idarraysize - 2] = id;
  repo->lastmarkerpos--;	/* marker has been moved */
  return olddeps;
}