| 6418 | } |
| 6419 | |
| 6420 | static int arch_layers(cbm_store_t *s, const char *project, const char *path, |
| 6421 | cbm_architecture_info_t *out) { |
| 6422 | /* Get boundaries for fan analysis */ |
| 6423 | cbm_cross_pkg_boundary_t *boundaries = NULL; |
| 6424 | int bcount = 0; |
| 6425 | int rc = arch_boundaries(s, project, path, &boundaries, &bcount); |
| 6426 | if (rc != CBM_STORE_OK) { |
| 6427 | return rc; |
| 6428 | } |
| 6429 | |
| 6430 | /* Collect route and entry point packages */ |
| 6431 | char *route_pkgs[CBM_SZ_32]; |
| 6432 | int nrpkgs = |
| 6433 | collect_pkg_names(s, "SELECT qualified_name FROM nodes WHERE project=?1 AND label='Route'", |
| 6434 | project, path, route_pkgs, CBM_SZ_32); |
| 6435 | |
| 6436 | char *entry_pkgs[CBM_SZ_32]; |
| 6437 | int nepkgs = collect_pkg_names(s, |
| 6438 | "SELECT qualified_name FROM nodes WHERE project=?1 AND " |
| 6439 | "json_extract(properties, '$.is_entry_point') = 1", |
| 6440 | project, path, entry_pkgs, CBM_SZ_32); |
| 6441 | |
| 6442 | /* Compute fan-in/out per package */ |
| 6443 | char *all_pkgs[CBM_SZ_64]; |
| 6444 | int fan_in[CBM_SZ_64]; |
| 6445 | int fan_out[CBM_SZ_64]; |
| 6446 | int npkgs = 0; |
| 6447 | memset(fan_in, 0, sizeof(fan_in)); |
| 6448 | memset(fan_out, 0, sizeof(fan_out)); |
| 6449 | |
| 6450 | for (int i = 0; i < bcount; i++) { |
| 6451 | int fi = find_or_add_pkg(all_pkgs, &npkgs, ST_MAX_PKGS, boundaries[i].from); |
| 6452 | if (fi >= 0) { |
| 6453 | fan_out[fi] += boundaries[i].call_count; |
| 6454 | } |
| 6455 | int ti = find_or_add_pkg(all_pkgs, &npkgs, ST_MAX_PKGS, boundaries[i].to); |
| 6456 | if (ti >= 0) { |
| 6457 | fan_in[ti] += boundaries[i].call_count; |
| 6458 | } |
| 6459 | } |
| 6460 | |
| 6461 | /* Also include route/entry packages */ |
| 6462 | for (int i = 0; i < nrpkgs; i++) { |
| 6463 | find_or_add_pkg(all_pkgs, &npkgs, ST_MAX_PKGS, route_pkgs[i]); |
| 6464 | } |
| 6465 | for (int i = 0; i < nepkgs; i++) { |
| 6466 | find_or_add_pkg(all_pkgs, &npkgs, ST_MAX_PKGS, entry_pkgs[i]); |
| 6467 | } |
| 6468 | |
| 6469 | /* Classify each package */ |
| 6470 | out->layers = (npkgs > 0) ? calloc(npkgs, sizeof(cbm_package_layer_t)) : NULL; |
| 6471 | out->layer_count = npkgs; |
| 6472 | for (int i = 0; i < npkgs; i++) { |
| 6473 | bool has_route = pkg_in_list(all_pkgs[i], route_pkgs, nrpkgs); |
| 6474 | bool has_entry = pkg_in_list(all_pkgs[i], entry_pkgs, nepkgs); |
| 6475 | const char *layer; |
| 6476 | const char *reason; |
| 6477 | classify_layer(all_pkgs[i], fan_in[i], fan_out[i], has_route, has_entry, &layer, &reason); |
no test coverage detected