sphor.c (6070B)
1 /* Copyright (C) 2024-2026 Centre National de la Recherche Scientifique 2 * Copyright (C) 2024-2026 Clermont Auvergne INP 3 * Copyright (C) 2024-2026 INSA Lyon 4 * Copyright (C) 2024-2026 Institut Mines Télécom Albi-Carmaux 5 * Copyright (C) 2024-2026 Institut National Polytechnique de Toulouse 6 * Copyright (C) 2024-2026 |Méso|Star> (contact@meso-star.com) 7 * Copyright (C) 2024-2026 PhotonLyX (info@photonlyx.com) 8 * Copyright (C) 2024-2026 Université de Lorraine 9 * Copyright (C) 2024-2026 Université Paul Sabatier 10 * Copyright (C) 2024-2026 Université Toulouse - Jean Jaurès 11 * 12 * This program is free software: you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation, either version 3 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 24 25 #include "sphor.h" 26 #include "sphor_c.h" 27 #include "sphor_config.h" 28 #include "sphor_compute_mvrea.h" 29 30 #include <star/sphin.h> 31 #include <star/s3d.h> 32 #include <star/ssp.h> 33 34 #include <rsys/logger.h> 35 #include <rsys/mem_allocator.h> 36 37 #include <errno.h> /* errno and EEXIST */ 38 #include <fcntl.h> /* open */ 39 #include <unistd.h> /* close */ 40 #include <sys/stat.h> /* S_IRUSR & S_IWUSR */ 41 42 /******************************************************************************* 43 * Helper functions 44 ******************************************************************************/ 45 static res_T 46 check_sphor_create_args 47 (const struct sphor_create_args* args) 48 { 49 if (NULL == args) { 50 return RES_BAD_ARG; 51 } 52 return RES_OK; 53 } 54 55 static void 56 release_sphor 57 (ref_T* address) 58 { 59 struct sphor* sphor = NULL; 60 ASSERT(NULL != address); 61 62 sphor = CONTAINER_OF(address, struct sphor, ref); 63 if (NULL != sphor->config) { 64 sphin_config_ref_put(sphor->config); 65 } 66 if (NULL != sphor->scene_view) { 67 s3d_scene_view_ref_put(sphor->scene_view); 68 } 69 if (NULL != sphor->source_distrib_power) { 70 ssp_ranst_discrete_ref_put(sphor->source_distrib_power); 71 } 72 if (NULL != sphor->stream) { fclose(sphor->stream); } 73 darray_interface_release(&sphor->interfaces); 74 darray_source_view_release(&sphor->source_views); 75 MEM_RM(sphor->allocator, sphor); 76 } 77 78 /******************************************************************************* 79 * Local functions 80 ******************************************************************************/ 81 FILE* 82 open_output_stream 83 (const struct sphor_create_args* args, 84 const struct sphor* sphor) 85 { 86 FILE* fp = NULL; 87 int fd = -1; 88 89 if (args->force) { 90 fp = fopen(args->output_filename, "w"); 91 if (NULL == fp) { 92 ERROR 93 (sphor, "Could not open output file `%s'\n", args->output_filename); 94 goto error; 95 } 96 } else { 97 fd = open 98 (args->output_filename, 99 O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 100 S_IRUSR | S_IWUSR); 101 if (fd >= 0) { 102 fp = fdopen(fd, "w"); 103 if (NULL == fp) { 104 ERROR 105 (sphor, "Could not open output file `%s'\n", args->output_filename); 106 goto error; 107 } 108 } else if (errno == EEXIST) { 109 ERROR 110 (sphor, "The output file `%s' already exists'\n", 111 args->output_filename); 112 goto error; 113 } else { 114 ERROR 115 (sphor, 116 "Unexpected error while opening output file `%s'\n", 117 args->output_filename); 118 goto error; 119 } 120 } 121 122 exit: 123 return fp; 124 error: 125 if (NULL != fp) { 126 fclose(fp); 127 fp = NULL; 128 } else if (fd >= 0) { 129 close(fd); 130 } 131 goto exit; 132 } 133 134 /******************************************************************************* 135 * Exported functions 136 ******************************************************************************/ 137 res_T 138 sphor_create 139 (const struct sphor_create_args* args, 140 struct sphor** out_sphor) 141 { 142 struct mem_allocator* allocator = NULL; 143 struct sphor* sphor = NULL; 144 res_T res = RES_OK; 145 146 if (NULL == out_sphor) { 147 res = RES_BAD_ARG; 148 goto error; 149 } 150 res = check_sphor_create_args(args); 151 if (RES_OK != res) goto error; 152 153 if (NULL == args->allocator) { 154 allocator = &mem_default_allocator; 155 } else { 156 allocator = args->allocator; 157 } 158 sphor = MEM_CALLOC(allocator, 1, sizeof(struct sphor)); 159 if (NULL == sphor) { 160 res = RES_MEM_ERR; 161 goto error; 162 } 163 ref_init(&sphor->ref); 164 sphor->verbose = args->verbose; 165 sphor->allocator = allocator; 166 sphor->nthreads = args->nthreads; 167 sphor->samples = args->samples; 168 if (NULL == args->logger) { 169 sphor->logger = LOGGER_DEFAULT; 170 } else { 171 sphor->logger = args->logger; 172 } 173 darray_interface_init(sphor->allocator, &sphor->interfaces); 174 darray_source_view_init(sphor->allocator, &sphor->source_views); 175 176 if (NULL != args->output_filename){ 177 sphor->stream = open_output_stream(args, sphor); 178 if (NULL == sphor->stream) { goto error; } 179 } else { sphor->stream = stdout; } 180 181 /* Load the system and build data structure for Monte Carlo */ 182 res = setup_config(sphor, args); 183 if (RES_OK != res) { goto error; } 184 185 exit: 186 if (NULL != out_sphor) *out_sphor = sphor; 187 return res; 188 error: 189 if (NULL != sphor) { 190 SPHOR(ref_put(sphor)); /* <=> ASSERT(sphor_ref_put(sphor) == RES_OK) */ 191 sphor = NULL; 192 } 193 goto exit; 194 } 195 196 res_T 197 sphor_ref_get(struct sphor* sphor) 198 { 199 if (NULL == sphor) { 200 return RES_BAD_ARG; 201 } 202 ref_get(&sphor->ref); 203 return RES_OK; 204 } 205 206 res_T 207 sphor_ref_put(struct sphor* sphor) 208 { 209 if (NULL == sphor) { 210 return RES_BAD_ARG; 211 } 212 ref_put(&sphor->ref, release_sphor); 213 return RES_OK; 214 } 215 216 res_T 217 sphor_run(struct sphor* sphor) 218 { 219 res_T res = RES_OK; 220 221 if (NULL == sphor) { goto error; } 222 223 res = sphor_compute_MVREA(sphor); 224 if (RES_OK != res) { goto error; } 225 226 exit: 227 return res; 228 error: 229 goto exit; 230 }