| 6207 | } |
| 6208 | |
| 6209 | static int arch_layers(cbm_store_t *s, const char *project, const char *path, |
| 6210 | cbm_architecture_info_t *out) { |
| 6211 | /* Get boundaries for fan analysis */ |
| 6212 | cbm_cross_pkg_boundary_t *boundaries = NULL; |
| 6213 | int bcount = 0; |
| 6214 | int rc = arch_boundaries(s, project, path, &boundaries, &bcount); |
| 6215 | if (rc != CBM_STORE_OK) { |
| 6216 | return rc; |
| 6217 | } |
| 6218 | |
| 6219 | /* Collect route and entry point packages */ |
| 6220 | char *route_pkgs[CBM_SZ_32]; |
| 6221 | int nrpkgs = |
| 6222 | collect_pkg_names(s, "SELECT qualified_name FROM nodes WHERE project=?1 AND label='Route'", |
| 6223 | project, path, route_pkgs, CBM_SZ_32); |
| 6224 | |
| 6225 | char *entry_pkgs[CBM_SZ_32]; |
| 6226 | int nepkgs = collect_pkg_names(s, |
| 6227 | "SELECT qualified_name FROM nodes WHERE project=?1 AND " |
| 6228 | "json_extract(properties, '$.is_entry_point') = 1", |
| 6229 | project, path, entry_pkgs, CBM_SZ_32); |
| 6230 | |
| 6231 | /* Compute fan-in/out per package */ |
| 6232 | char *all_pkgs[CBM_SZ_64]; |
| 6233 | int fan_in[CBM_SZ_64]; |
| 6234 | int fan_out[CBM_SZ_64]; |
| 6235 | int npkgs = 0; |
| 6236 | memset(fan_in, 0, sizeof(fan_in)); |
| 6237 | memset(fan_out, 0, sizeof(fan_out)); |
| 6238 | |
| 6239 | for (int i = 0; i < bcount; i++) { |
| 6240 | int fi = find_or_add_pkg(all_pkgs, &npkgs, ST_MAX_PKGS, boundaries[i].from); |
| 6241 | if (fi >= 0) { |
| 6242 | fan_out[fi] += boundaries[i].call_count; |
| 6243 | } |
| 6244 | int ti = find_or_add_pkg(all_pkgs, &npkgs, ST_MAX_PKGS, boundaries[i].to); |
| 6245 | if (ti >= 0) { |
| 6246 | fan_in[ti] += boundaries[i].call_count; |
| 6247 | } |
| 6248 | } |
| 6249 | |
| 6250 | /* Also include route/entry packages */ |
| 6251 | for (int i = 0; i < nrpkgs; i++) { |
| 6252 | find_or_add_pkg(all_pkgs, &npkgs, ST_MAX_PKGS, route_pkgs[i]); |
| 6253 | } |
| 6254 | for (int i = 0; i < nepkgs; i++) { |
| 6255 | find_or_add_pkg(all_pkgs, &npkgs, ST_MAX_PKGS, entry_pkgs[i]); |
| 6256 | } |
| 6257 | |
| 6258 | /* Classify each package */ |
| 6259 | out->layers = (npkgs > 0) ? calloc(npkgs, sizeof(cbm_package_layer_t)) : NULL; |
| 6260 | out->layer_count = npkgs; |
| 6261 | for (int i = 0; i < npkgs; i++) { |
| 6262 | bool has_route = pkg_in_list(all_pkgs[i], route_pkgs, nrpkgs); |
| 6263 | bool has_entry = pkg_in_list(all_pkgs[i], entry_pkgs, nepkgs); |
| 6264 | const char *layer; |
| 6265 | const char *reason; |
| 6266 | classify_layer(all_pkgs[i], fan_in[i], fan_out[i], has_route, has_entry, &layer, &reason); |
no test coverage detected