| 6308 | } |
| 6309 | |
| 6310 | static int arch_layers(cbm_store_t *s, const char *project, const char *path, |
| 6311 | cbm_architecture_info_t *out) { |
| 6312 | /* Get boundaries for fan analysis */ |
| 6313 | cbm_cross_pkg_boundary_t *boundaries = NULL; |
| 6314 | int bcount = 0; |
| 6315 | int rc = arch_boundaries(s, project, path, &boundaries, &bcount); |
| 6316 | if (rc != CBM_STORE_OK) { |
| 6317 | return rc; |
| 6318 | } |
| 6319 | |
| 6320 | /* Collect route and entry point packages */ |
| 6321 | char *route_pkgs[CBM_SZ_32]; |
| 6322 | int nrpkgs = |
| 6323 | collect_pkg_names(s, "SELECT qualified_name FROM nodes WHERE project=?1 AND label='Route'", |
| 6324 | project, path, route_pkgs, CBM_SZ_32); |
| 6325 | |
| 6326 | char *entry_pkgs[CBM_SZ_32]; |
| 6327 | int nepkgs = collect_pkg_names(s, |
| 6328 | "SELECT qualified_name FROM nodes WHERE project=?1 AND " |
| 6329 | "json_extract(properties, '$.is_entry_point') = 1", |
| 6330 | project, path, entry_pkgs, CBM_SZ_32); |
| 6331 | |
| 6332 | /* Compute fan-in/out per package */ |
| 6333 | char *all_pkgs[CBM_SZ_64]; |
| 6334 | int fan_in[CBM_SZ_64]; |
| 6335 | int fan_out[CBM_SZ_64]; |
| 6336 | int npkgs = 0; |
| 6337 | memset(fan_in, 0, sizeof(fan_in)); |
| 6338 | memset(fan_out, 0, sizeof(fan_out)); |
| 6339 | |
| 6340 | for (int i = 0; i < bcount; i++) { |
| 6341 | int fi = find_or_add_pkg(all_pkgs, &npkgs, ST_MAX_PKGS, boundaries[i].from); |
| 6342 | if (fi >= 0) { |
| 6343 | fan_out[fi] += boundaries[i].call_count; |
| 6344 | } |
| 6345 | int ti = find_or_add_pkg(all_pkgs, &npkgs, ST_MAX_PKGS, boundaries[i].to); |
| 6346 | if (ti >= 0) { |
| 6347 | fan_in[ti] += boundaries[i].call_count; |
| 6348 | } |
| 6349 | } |
| 6350 | |
| 6351 | /* Also include route/entry packages */ |
| 6352 | for (int i = 0; i < nrpkgs; i++) { |
| 6353 | find_or_add_pkg(all_pkgs, &npkgs, ST_MAX_PKGS, route_pkgs[i]); |
| 6354 | } |
| 6355 | for (int i = 0; i < nepkgs; i++) { |
| 6356 | find_or_add_pkg(all_pkgs, &npkgs, ST_MAX_PKGS, entry_pkgs[i]); |
| 6357 | } |
| 6358 | |
| 6359 | /* Classify each package */ |
| 6360 | out->layers = (npkgs > 0) ? calloc(npkgs, sizeof(cbm_package_layer_t)) : NULL; |
| 6361 | out->layer_count = npkgs; |
| 6362 | for (int i = 0; i < npkgs; i++) { |
| 6363 | bool has_route = pkg_in_list(all_pkgs[i], route_pkgs, nrpkgs); |
| 6364 | bool has_entry = pkg_in_list(all_pkgs[i], entry_pkgs, nepkgs); |
| 6365 | const char *layer; |
| 6366 | const char *reason; |
| 6367 | classify_layer(all_pkgs[i], fan_in[i], fan_out[i], has_route, has_entry, &layer, &reason); |
no test coverage detected