Imported Upstream version 0.7.12
[platform/upstream/libsolv.git] / ext / repodata_diskusage.c
1 /*
2  * repodata_diskusage.c
3  *
4  * Small helper to convert diskusage data from sustags or rpmmd
5  *
6  * Copyright (c) 2017, Novell Inc.
7  *
8  * This program is licensed under the BSD license, read LICENSE.BSD
9  * for further information
10  */
11
12 #include <sys/types.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16
17 #include "pool.h"
18 #include "repo.h"
19 #include "util.h"
20 #include "repodata_diskusage.h"
21
22 /* The queue contains (dirid, kbytes, inodes) triplets */
23
24 static int
25 add_diskusage_sortfn(const void *ap, const void *bp, void *dp)
26 {
27   return *(Id *)ap - *(Id *)bp;
28 }
29
30 void
31 repodata_add_diskusage(Repodata *data, Id handle, Queue *q)
32 {
33   int i, j;
34   Dirpool *dp = &data->dirpool;
35
36   /* Sort in dirid order. This ensures that parents come before
37    * their children. */
38   if (q->count > 3)
39     solv_sort(q->elements, q->count / 3, 3 * sizeof(Id), add_diskusage_sortfn, 0);
40   for (i = 3; i < q->count; i += 3)
41     {
42       /* subtract data from parent */
43       Id did = q->elements[i];
44       if (i + 3 < q->count && q->elements[i + 3] == did)
45         {
46           /* identical directory entry! zero this one */
47           q->elements[i + 1] = 0;
48           q->elements[i + 2] = 0;
49           continue;
50         }
51       while (did)
52         {
53           did = dirpool_parent(dp, did);
54           for (j = i - 3; j >= 0; j -= 3)
55             if (q->elements[j] == did)
56               break;
57           if (j >= 0)
58             {
59               if ((unsigned int)q->elements[j + 1] > (unsigned int)q->elements[i + 1])
60                 q->elements[j + 1] -= q->elements[i + 1];
61               else
62                 q->elements[j + 1] = 0;
63               if ((unsigned int)q->elements[j + 2] > (unsigned int)q->elements[i + 2])
64                 q->elements[j + 2] -= q->elements[i + 2];
65               else
66                 q->elements[j + 2] = 0;
67               break;
68             }
69         }
70     }
71   /* now commit data */
72   for (i = 0; i < q->count; i += 3)
73     if (q->elements[i + 1] || q->elements[i + 2])
74       repodata_add_dirnumnum(data, handle, SOLVABLE_DISKUSAGE, q->elements[i], q->elements[i + 1], q->elements[i + 2]);
75   /* empty queue */
76   queue_empty(q);
77 }
78