Gentoo Archives: gentoo-commits

From: Fabian Groffen <grobian@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] repo/proj/prefix:master commit in: scripts/rsync-generation/
Date: Wed, 28 Feb 2018 18:44:55
Message-Id: 1519843411.a11406710f526f2b28e68f5544e6cd9e47710058.grobian@gentoo
1 commit: a11406710f526f2b28e68f5544e6cd9e47710058
2 Author: Fabian Groffen <grobian <AT> gentoo <DOT> org>
3 AuthorDate: Wed Feb 28 18:43:31 2018 +0000
4 Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org>
5 CommitDate: Wed Feb 28 18:43:31 2018 +0000
6 URL: https://gitweb.gentoo.org/repo/proj/prefix.git/commit/?id=a1140671
7
8 scripts/rsync-generation/hashgen: allow verification to be massively parallel
9
10 save up subdirs to handle so we can nicely loop over them in a for-loop
11 which OpenMP can cheaply parallelise for us (for free)
12
13 scripts/rsync-generation/hashgen.c | 109 +++++++++++++++++++++++++++----------
14 1 file changed, 79 insertions(+), 30 deletions(-)
15
16 diff --git a/scripts/rsync-generation/hashgen.c b/scripts/rsync-generation/hashgen.c
17 index 3f7aaf65d6..b2ba8b0f5a 100644
18 --- a/scripts/rsync-generation/hashgen.c
19 +++ b/scripts/rsync-generation/hashgen.c
20 @@ -919,6 +919,12 @@ compare_strings(const void *l, const void *r)
21
22 static char verify_manifest(const char *dir, const char *manifest);
23
24 +struct subdir_workload {
25 + size_t subdirlen;
26 + size_t elemslen;
27 + char **elems;
28 +};
29 +
30 #define LISTSZ 64
31 static char
32 verify_dir(
33 @@ -940,6 +946,9 @@ verify_dir(
34 char etpe;
35 char ret = 0;
36 int cmp;
37 + struct subdir_workload **subdir = NULL;
38 + size_t subdirsize = 0;
39 + size_t subdirlen = 0;
40
41 /* shortcut a single Manifest entry pointing to the same dir
42 * (happens at top-level) */
43 @@ -1013,40 +1022,41 @@ verify_dir(
44 /* handle subdirs first */
45 if ((slash = strchr(entry, '/')) != NULL) {
46 size_t sublen = slash - entry;
47 - char ndir[8192];
48 -
49 - if (etpe == 'M') {
50 - size_t skiplen = strlen(dir) + 1 + sublen;
51 - /* sub-Manifest, we need to do a proper recurse */
52 - slash = strrchr(entry, '/'); /* cannot be NULL */
53 - snprintf(ndir, sizeof(ndir), "%s/%s", dir, entry);
54 - ndir[skiplen] = '\0';
55 - slash = strchr(ndir + skiplen + 1, ' ');
56 - if (slash != NULL) /* path should fit in ndir ... */
57 - *slash = '\0';
58 - if (verify_file(dir, entry, mfest) != 0 ||
59 - verify_manifest(ndir, ndir + skiplen + 1) != 0)
60 - ret |= 1;
61 - } else {
62 - int elemstart = curelem;
63 - char **subelems = &elems[curelem];
64 - /* collect all entries like this one (same subdir) into
65 - * a sub-list that we can verify */
66 + int elemstart = curelem;
67 + char **subelems = &elems[curelem];
68 +
69 + /* collect all entries like this one (same subdir) into
70 + * a sub-list that we can verify */
71 + curelem++;
72 + while (curelem < elemslen &&
73 + strncmp(entry, elems[curelem] + 2 + skippath,
74 + sublen + 1) == 0)
75 curelem++;
76 - while (curelem < elemslen &&
77 - strncmp(entry, elems[curelem] + 2 + skippath,
78 - sublen + 1) == 0)
79 - curelem++;
80 - snprintf(ndir, sizeof(ndir), "%s/%.*s", dir,
81 - (int)sublen, elems[elemstart] + 2 + skippath);
82 - ret |= verify_dir(ndir, subelems,
83 - curelem - elemstart, skippath + sublen + 1, mfest);
84 - curelem--; /* move back, see below */
85 +
86 + if (subdirlen == subdirsize) {
87 + subdirsize += LISTSZ;
88 + subdir = realloc(subdir,
89 + subdirsize * sizeof(subdir[0]));
90 + if (subdir == NULL) {
91 + fprintf(stderr, "out of memory\n");
92 + return 1;
93 + }
94 + }
95 + subdir[subdirlen] = malloc(sizeof(struct subdir_workload));
96 + if (subdir[subdirlen] == NULL) {
97 + fprintf(stderr, "out of memory\n");
98 + return 1;
99 }
100 -
101 + subdir[subdirlen]->subdirlen = sublen;
102 + subdir[subdirlen]->elemslen = curelem - elemstart;
103 + subdir[subdirlen]->elems = subelems;
104 + subdirlen++;
105 +
106 + curelem--; /* move back, see below */
107 +
108 /* modify the last entry to be the subdir, such that we
109 * can let the code below synchronise with dentries */
110 - elems[curelem][2 + skippath + sublen] = '\0';
111 + elems[curelem][2 + skippath + sublen] = ' ';
112 entry = elems[curelem] + 2 + skippath;
113 etpe = 'S'; /* flag this was a subdir */
114 }
115 @@ -1083,6 +1093,8 @@ verify_dir(
116 *slash = '\0';
117 fprintf(stderr, "%s: missing %s file: %s\n",
118 mfest, etpe == 'M' ? "MANIFEST" : "DATA", entry);
119 + if (slash != NULL)
120 + *slash = ' ';
121 }
122 curelem++;
123 } else if (cmp > 0) {
124 @@ -1098,6 +1110,43 @@ verify_dir(
125 free(dentries[dentrieslen]);
126 free(dentries);
127
128 +#pragma omp parallel for shared(ret) private(entry, etpe, slash)
129 + for (cmp = 0; cmp < subdirlen; cmp++) {
130 + char ndir[8192];
131 +
132 + entry = subdir[cmp]->elems[0] + 2 + skippath;
133 + etpe = subdir[cmp]->elems[0][0];
134 +
135 + /* restore original entry format */
136 + subdir[cmp]->elems[subdir[cmp]->elemslen - 1]
137 + [2 + skippath + subdir[cmp]->subdirlen] = '/';
138 +
139 + if (etpe == 'M') {
140 + size_t skiplen = strlen(dir) + 1 + subdir[cmp]->subdirlen;
141 + /* sub-Manifest, we need to do a proper recurse */
142 + slash = strrchr(entry, '/'); /* cannot be NULL */
143 + snprintf(ndir, sizeof(ndir), "%s/%s", dir, entry);
144 + ndir[skiplen] = '\0';
145 + slash = strchr(ndir + skiplen + 1, ' ');
146 + if (slash != NULL) /* path should fit in ndir ... */
147 + *slash = '\0';
148 + if (verify_file(dir, entry, mfest) != 0 ||
149 + verify_manifest(ndir, ndir + skiplen + 1) != 0)
150 + ret |= 1;
151 + } else {
152 + snprintf(ndir, sizeof(ndir), "%s/%.*s", dir,
153 + (int)subdir[cmp]->subdirlen, entry);
154 + ret |= verify_dir(ndir, subdir[cmp]->elems,
155 + subdir[cmp]->elemslen,
156 + skippath + subdir[cmp]->subdirlen + 1, mfest);
157 + }
158 +
159 + free(subdir[cmp]);
160 + }
161 +
162 + if (subdir)
163 + free(subdir);
164 +
165 return ret;
166 } else {
167 return 1;