summaryrefslogtreecommitdiff
path: root/src/source.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/source.c')
-rw-r--r--src/source.c283
1 files changed, 283 insertions, 0 deletions
diff --git a/src/source.c b/src/source.c
new file mode 100644
index 0000000..e3582c6
--- /dev/null
+++ b/src/source.c
@@ -0,0 +1,283 @@
+/*
+ * source.c
+ *
+ * Manage metadata coming from one repository
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "source.h"
+#include "pool.h"
+#include "poolid_private.h"
+#include "util.h"
+
+#define IDARRAY_BLOCK 4095
+
+/*
+ * get name of source
+ */
+
+const char *
+source_name(const Source *source)
+{
+ return source->name;
+}
+
+
+/*
+ * create empty source
+ * and add to pool
+ */
+
+Source *
+pool_addsource_empty(Pool *pool)
+{
+ Source *source;
+
+ pool_freewhatprovides(pool);
+ source = (Source *)xcalloc(1, sizeof(*source));
+ pool->sources = (Source **)xrealloc(pool->sources, (pool->nsources + 1) * sizeof(Source *));
+ pool->sources[pool->nsources++] = source;
+ source->name = "empty";
+ source->pool = pool;
+ source->start = pool->nsolvables;
+ source->nsolvables = 0;
+ return source;
+}
+
+/*
+ * add Id to source
+ * olddeps = offset into idarraydata
+ *
+ */
+
+unsigned int
+source_addid(Source *source, Offset olddeps, Id id)
+{
+ Id *idarray;
+ int idarraysize;
+ int i;
+
+ idarray = source->idarraydata;
+ idarraysize = source->idarraysize;
+
+ if (!idarray) /* check idarray size */
+ {
+ idarray = (Id *)xmalloc((1 + IDARRAY_BLOCK) * sizeof(Id));
+ idarraysize = 1;
+ source->lastoff = 0;
+ }
+
+ if (!olddeps) /* no deps yet */
+ {
+ olddeps = idarraysize;
+ if ((idarraysize & IDARRAY_BLOCK) == 0)
+ idarray = (Id *)xrealloc(idarray, (idarraysize + 1 + IDARRAY_BLOCK) * sizeof(Id));
+ }
+ else if (olddeps == source->lastoff) /* append at end */
+ idarraysize--;
+ else /* check space */
+ {
+ i = olddeps;
+ olddeps = idarraysize;
+ for (; idarray[i]; i++)
+ {
+ if ((idarraysize & IDARRAY_BLOCK) == 0)
+ idarray = (Id *)xrealloc(idarray, (idarraysize + 1 + IDARRAY_BLOCK) * sizeof(Id));
+ idarray[idarraysize++] = idarray[i];
+ }
+ if ((idarraysize & IDARRAY_BLOCK) == 0)
+ idarray = (Id *)xrealloc(idarray, (idarraysize + 1 + IDARRAY_BLOCK) * sizeof(Id));
+ }
+
+ idarray[idarraysize++] = id; /* insert Id into array */
+
+ if ((idarraysize & IDARRAY_BLOCK) == 0) /* realloc if at block boundary */
+ idarray = (Id *)xrealloc(idarray, (idarraysize + 1 + IDARRAY_BLOCK) * sizeof(Id));
+
+ idarray[idarraysize++] = ID_NULL; /* ensure NULL termination */
+
+ source->idarraydata = idarray;
+ source->idarraysize = idarraysize;
+ source->lastoff = olddeps;
+
+ return olddeps;
+}
+
+
+/*
+ * add dependency (as Id) to source
+ * olddeps = offset into idarraydata
+ * isreq = 0 for normal dep
+ * isreq = 1 for requires
+ * isreq = 2 for pre-requires
+ *
+ */
+
+unsigned int
+source_addid_dep(Source *source, Offset olddeps, Id id, int isreq)
+{
+ Id oid, *oidp, *marker = 0;
+
+ if (!olddeps)
+ return source_addid(source, olddeps, id);
+
+ if (!isreq)
+ {
+ for (oidp = source->idarraydata + olddeps; (oid = *oidp) != ID_NULL; oidp++)
+ {
+ if (oid == id)
+ return olddeps;
+ }
+ return source_addid(source, olddeps, id);
+ }
+
+ for (oidp = source->idarraydata + olddeps; (oid = *oidp) != ID_NULL; oidp++)
+ {
+ if (oid == SOLVABLE_PREREQMARKER)
+ marker = oidp;
+ else if (oid == id)
+ break;
+ }
+
+ if (oid)
+ {
+ if (marker || isreq == 1)
+ return olddeps;
+ marker = oidp++;
+ for (; (oid = *oidp) != ID_NULL; oidp++)
+ if (oid == SOLVABLE_PREREQMARKER)
+ break;
+ if (!oid)
+ {
+ oidp--;
+ if (marker < oidp)
+ memmove(marker, marker + 1, (oidp - marker) * sizeof(Id));
+ *oidp = SOLVABLE_PREREQMARKER;
+ return source_addid(source, olddeps, id);
+ }
+ while (oidp[1])
+ oidp++;
+ memmove(marker, marker + 1, (oidp - marker) * sizeof(Id));
+ *oidp = id;
+ return olddeps;
+ }
+ if (isreq == 2 && !marker)
+ olddeps = source_addid(source, olddeps, SOLVABLE_PREREQMARKER);
+ else if (isreq == 1 && marker)
+ {
+ *marker++ = id;
+ id = *--oidp;
+ if (marker < oidp)
+ memmove(marker + 1, marker, (oidp - marker) * sizeof(Id));
+ *marker = SOLVABLE_PREREQMARKER;
+ }
+ return source_addid(source, olddeps, id);
+}
+
+
+/*
+ * reserve Ids
+ * make space for 'num' more dependencies
+ */
+
+unsigned int
+source_reserve_ids(Source *source, unsigned int olddeps, int num)
+{
+ num++; /* room for trailing ID_NULL */
+
+ if (!source->idarraysize) /* ensure buffer space */
+ {
+ source->idarraysize = 1;
+ source->idarraydata = (Id *)xmalloc(((1 + num + IDARRAY_BLOCK) & ~IDARRAY_BLOCK) * sizeof(Id));
+ source->lastoff = 1;
+ return 1;
+ }
+
+ if (olddeps && olddeps != source->lastoff) /* if not appending */
+ {
+ /* can't insert into idarray, this would invalidate all 'larger' offsets
+ * so create new space at end and move existing deps there.
+ * Leaving 'hole' at old position.
+ */
+
+ Id *idstart, *idend;
+ int count;
+
+ for (idstart = idend = source->idarraydata + olddeps; *idend++; ) /* find end */
+ ;
+ count = idend - idstart - 1 + num; /* new size */
+
+ /* realloc if crossing block boundary */
+ if (((source->idarraysize - 1) | IDARRAY_BLOCK) != ((source->idarraysize + count - 1) | IDARRAY_BLOCK))
+ source->idarraydata = (Id *)xrealloc(source->idarraydata, ((source->idarraysize + count + IDARRAY_BLOCK) & ~IDARRAY_BLOCK) * sizeof(Id));
+
+ /* move old deps to end */
+ olddeps = source->lastoff = source->idarraysize;
+ memcpy(source->idarraydata + olddeps, idstart, count - num);
+ source->idarraysize = olddeps + count - num;
+
+ return olddeps;
+ }
+
+ if (olddeps) /* appending */
+ source->idarraysize--;
+
+ /* realloc if crossing block boundary */
+ if (((source->idarraysize - 1) | IDARRAY_BLOCK) != ((source->idarraysize + num - 1) | IDARRAY_BLOCK))
+ source->idarraydata = (Id *)xrealloc(source->idarraydata, ((source->idarraysize + num + IDARRAY_BLOCK) & ~IDARRAY_BLOCK) * sizeof(Id));
+
+ /* appending or new */
+ source->lastoff = olddeps ? olddeps : source->idarraysize;
+
+ return source->lastoff;
+}
+
+
+/*
+ * remove source from pool
+ *
+ */
+
+void
+pool_freesource(Pool *pool, Source *source)
+{
+ int i, nsolvables;
+
+ pool_freewhatprovides(pool);
+
+ for (i = 0; i < pool->nsources; i++) /* find source in pool */
+ {
+ if (pool->sources[i] == source)
+ break;
+ }
+ if (i == pool->nsources) /* source not in pool, return */
+ return;
+
+ /* close gap
+ * all sources point into pool->solvables _relatively_ to source->start
+ * so closing the gap only needs adaption of source->start for all
+ * other sources.
+ */
+
+ nsolvables = source->nsolvables;
+ if (pool->nsolvables > source->start + nsolvables)
+ memmove(pool->solvables + source->start, pool->solvables + source->start + nsolvables, (pool->nsolvables - source->start - nsolvables) * sizeof(Solvable));
+ pool->nsolvables -= nsolvables;
+
+ for (; i < pool->nsources - 1; i++)
+ {
+ pool->sources[i] = pool->sources[i + 1]; /* remove source */
+ pool->sources[i]->start -= nsolvables; /* adapt start offset of remaining sources */
+ }
+ pool->nsources = i;
+
+ xfree(source->idarraydata);
+ xfree(source->rpmdbid);
+ xfree(source);
+}
+
+// EOF