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; |