#define _POSIX_C_SOURCE 200809L #include "catalog.h" #include #include #include #include static int write_tile(const char *directory, int ra_index, int dec_index, double longitude) { char path[4096]; const int written = snprintf(path, sizeof path, "%s/tile_ra%03d_dec%03d.csv", directory, ra_index, dec_index); if (written < 0 || written >= (int)sizeof path) return -1; FILE *file = fopen(path, "w"); if (file == NULL) return -1; const int result = fputs("longitude_deg,latitude_deg,temperature_K,amplitude\n", file) == EOF || fprintf(file, "%.1f,0,7000,1\n", longitude) < 0 || fclose(file) != 0; return result ? -1 : 0; } static int tile_state(const StarCatalog *catalog, int ra, int dec) { return catalog->tiles[(size_t)dec * CATALOG_ALL_SKY_RA_TILES + ra].state; } int main(void) { char directory[] = "/tmp/catalog_prefetch_XXXXXX"; char path[4096]; StarCatalog catalog = {0}; StarCatalog batched = {0}; int result = 1; if (mkdtemp(directory) == NULL || write_tile(directory, 0, 90, 0.0) || write_tile(directory, 1, 90, 1.0) || catalog_load_all_sky(&catalog, directory)) goto done; /* Two overlapping sets: A = {0,1}, B = {1,2}; the union is {0,1,2}, and * tile 2 is intentionally missing from disk. */ CatalogTileSet set_a; CatalogTileSet set_b; CatalogTileSet union_set; catalog_tile_set_clear(&set_a); catalog_tile_set_clear(&set_b); catalog_tile_set_clear(&union_set); set_a.requested[90 * CATALOG_ALL_SKY_RA_TILES] = 1; set_a.requested[90 * CATALOG_ALL_SKY_RA_TILES + 1] = 1; set_b.requested[90 * CATALOG_ALL_SKY_RA_TILES + 1] = 1; set_b.requested[90 * CATALOG_ALL_SKY_RA_TILES + 2] = 1; for (int ra = 0; ra < 3; ++ra) union_set.requested[90 * CATALOG_ALL_SKY_RA_TILES + ra] = set_a.requested[90 * CATALOG_ALL_SKY_RA_TILES + ra] || set_b.requested[90 * CATALOG_ALL_SKY_RA_TILES + ra]; if (catalog_tile_set_count(&set_a) != 2 || catalog_tile_set_count(&set_b) != 2 || catalog_tile_set_count(&union_set) != 3) { fputs("catalog tile-set union regression failed\n", stderr); goto done; } CatalogPrefetchStats first = {0}; if (catalog_prefetch_tile_set(&catalog, &union_set, 4, CATALOG_PREFETCH_DEFAULT_BATCH_TILES, &first) || first.requested_tiles != 3 || first.newly_loaded_tiles != 2 || first.unavailable_tiles != 1 || first.newly_loaded_stars != 2 || catalog.count != 2 || tile_state(&catalog, 0, 90) != 1 || tile_state(&catalog, 1, 90) != 1 || tile_state(&catalog, 2, 90) != -1) { fputs("parallel catalog union prefetch regression failed\n", stderr); goto done; } Star *first_tile = catalog.tiles[90 * CATALOG_ALL_SKY_RA_TILES].stars; /* Re-prefetching the same union must read nothing and must not re-mark the * unavailable tile. */ CatalogPrefetchStats second = {0}; if (catalog_prefetch_tile_set(&catalog, &union_set, 2, CATALOG_PREFETCH_DEFAULT_BATCH_TILES, &second) || second.requested_tiles != 3 || second.newly_loaded_tiles != 0 || second.unavailable_tiles != 0 || second.newly_loaded_stars != 0 || catalog.count != 2 || catalog.tiles[90 * CATALOG_ALL_SKY_RA_TILES].stars != first_tile) { fputs("catalog union prefetch cache reuse regression failed\n", stderr); goto done; } /* A batch size of one must reach the same final cache as the default. */ if (catalog_load_all_sky(&batched, directory) || catalog_prefetch_tile_set(&batched, &union_set, 4, 1, NULL) || batched.count != catalog.count || tile_state(&batched, 0, 90) != 1 || tile_state(&batched, 1, 90) != 1 || tile_state(&batched, 2, 90) != -1) { fputs("catalog single-tile batching regression failed\n", stderr); goto done; } result = 0; done: catalog_destroy(&catalog); catalog_destroy(&batched); for (int ra = 0; ra < 3; ++ra) { const int written = snprintf(path, sizeof path, "%s/tile_ra%03d_dec090.csv", directory, ra); if (written > 0 && written < (int)sizeof path) unlink(path); } rmdir(directory); return result; }