atrtp

Thermodynamic properties of a medium in combustion
git clone git://git.meso-star.fr/atrtp.git
Log | Files | Refs | README | LICENSE

atrtp.c (6534B)


      1 /* Copyright (C) 2022, 2023 |Méso|Star> (contact@meso-star.com)
      2  * Copyright (C) 2020, 2021 Centre National de la Recherche Scientifique
      3  *
      4  * This program is free software: you can redistribute it and/or modify
      5  * it under the terms of the GNU General Public License as published by
      6  * the Free Software Foundation, either version 3 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     12  * GNU General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program. If not, see <http://www.gnu.org/licenses/>. */
     16 
     17 #define _POSIX_C_SOURCE 200809L /* mmap support */
     18 #define _DEFAULT_SOURCE 1 /* MAP_POPULATE support */
     19 #define _BSD_SOURCE 1 /* MAP_POPULATE for glibc < 2.19 */
     20 
     21 #include "atrtp.h"
     22 #include "atrtp_c.h"
     23 #include "atrtp_log.h"
     24 
     25 #include <unistd.h>
     26 
     27 #include <errno.h>
     28 #include <sys/mman.h> /* mmap */
     29 
     30 /*******************************************************************************
     31  * Helper functions
     32  ******************************************************************************/
     33 static void
     34 reset_atrtp(struct atrtp* atrtp)
     35 {
     36   ASSERT(atrtp);
     37   atrtp->pagesize = 0;
     38   atrtp->nnodes = 0;
     39   if(atrtp->props) munmap(atrtp->props, atrtp->map_len);
     40   atrtp->props = NULL;
     41   atrtp->map_len = 0;
     42 }
     43 
     44 static res_T
     45 load_stream(struct atrtp* atrtp, FILE* stream, const char* stream_name)
     46 {
     47   off_t offset;
     48   size_t filesz;
     49   res_T res = RES_OK;
     50   ASSERT(atrtp && stream && stream_name);
     51 
     52   reset_atrtp(atrtp);
     53 
     54   /* Read file header */
     55   #define READ(Var, N, Name) {                                                 \
     56     if(fread((Var), sizeof(*(Var)), (N), stream) != (N)) {                     \
     57       log_err(atrtp, "%s: could not read the %s.\n", stream_name, (Name));     \
     58       res = RES_IO_ERR;                                                        \
     59       goto error;                                                              \
     60     }                                                                          \
     61   } (void)0
     62   READ(&atrtp->pagesize, 1, "page size");
     63   READ(&atrtp->nnodes, 1, "number of nodes");
     64   #undef READ
     65 
     66   if(!IS_ALIGNED(atrtp->pagesize, atrtp->pagesize_os)) {
     67     log_err(atrtp,
     68       "%s: invalid page size %li. The page size attribute must be aligned on "
     69       "the page size of the operating system (%lu).\n",
     70       stream_name, atrtp->pagesize, (unsigned long)atrtp->pagesize_os);
     71     res = RES_BAD_ARG;
     72     goto error;
     73   }
     74 
     75   /* Compute the length in bytes of the data to map */
     76   atrtp->map_len = atrtp->nnodes * sizeof(double[ATRTP_COUNT__]);
     77   atrtp->map_len = ALIGN_SIZE(atrtp->map_len, (size_t)atrtp->pagesize);
     78 
     79   /* Find the offsets of the positions/indices data into the stream */
     80   offset = (off_t)ALIGN_SIZE((uint64_t)ftell(stream), atrtp->pagesize);
     81 
     82   /* Retrieve the overall filesize */
     83   fseek(stream, 0, SEEK_END);
     84   filesz = (size_t)ftell(stream);
     85 
     86   /* Check that the file has sufficient data */
     87   if((size_t)offset + atrtp->map_len > filesz) {
     88     log_err(atrtp,
     89       "%s: the thermodynamic properties to load exceed the file size.\n",
     90       stream_name);
     91     res = RES_IO_ERR;
     92     goto error;
     93   }
     94 
     95   /* Map the thermodynamic properties */
     96   atrtp->props = mmap(NULL, atrtp->map_len, PROT_READ,
     97     MAP_PRIVATE|MAP_POPULATE, fileno(stream), offset);
     98   if(atrtp->props == MAP_FAILED) {
     99     log_err(atrtp, "%s: could not map the thermodynamic properties --%s.\n",
    100       stream_name, strerror(errno));
    101     res = RES_IO_ERR;
    102     goto error;
    103   }
    104 
    105 exit:
    106   return res;
    107 error:
    108   reset_atrtp(atrtp);
    109   goto exit;
    110 }
    111 
    112 static void
    113 release_atrtp(ref_T* ref)
    114 {
    115   struct atrtp* atrtp;
    116   ASSERT(ref);
    117   atrtp = CONTAINER_OF(ref, struct atrtp, ref);
    118   reset_atrtp(atrtp);
    119   if(atrtp->logger == &atrtp->logger__) logger_release(&atrtp->logger__);
    120   MEM_RM(atrtp->allocator, atrtp);
    121 }
    122 
    123 /*******************************************************************************
    124  * Exported functions
    125  ******************************************************************************/
    126 res_T
    127 atrtp_create
    128   (struct logger* logger, /* NULL <=> use default logger */
    129    struct mem_allocator* mem_allocator, /* NULL <=> use default allocator */
    130    const int verbose, /* Verbosity level */
    131    struct atrtp** out_atrtp)
    132 {
    133   struct atrtp* atrtp = NULL;
    134   struct mem_allocator* allocator = NULL;
    135   res_T res = RES_OK;
    136 
    137   if(!out_atrtp) {
    138     res = RES_BAD_ARG;
    139     goto error;
    140   }
    141 
    142   allocator = mem_allocator ? mem_allocator : &mem_default_allocator;
    143   atrtp = MEM_CALLOC(allocator, 1, sizeof(*atrtp));
    144   if(!atrtp) {
    145     if(verbose) {
    146       #define ERR_STR "Could not allocate the AtrTP device.\n"
    147       if(logger) {
    148         logger_print(logger, LOG_ERROR, ERR_STR);
    149       } else {
    150         fprintf(stderr, MSG_ERROR_PREFIX ERR_STR);
    151       }
    152       #undef ERR_STR
    153     }
    154     res = RES_MEM_ERR;
    155     goto error;
    156   }
    157   ref_init(&atrtp->ref);
    158   atrtp->allocator = allocator;
    159   atrtp->verbose = verbose;
    160   atrtp->pagesize_os = (size_t)sysconf(_SC_PAGESIZE);
    161   if(logger) {
    162     atrtp->logger = logger;
    163   } else {
    164     setup_log_default(atrtp);
    165   }
    166 
    167 exit:
    168   if(out_atrtp) *out_atrtp = atrtp;
    169   return res;
    170 error:
    171   if(atrtp) {
    172     ATRTP(ref_put(atrtp));
    173     atrtp = NULL;
    174   }
    175   goto exit;
    176 }
    177 
    178 res_T
    179 atrtp_ref_get(struct atrtp* atrtp)
    180 {
    181   if(!atrtp) return RES_BAD_ARG;
    182   ref_get(&atrtp->ref);
    183   return RES_OK;
    184 }
    185 
    186 res_T
    187 atrtp_ref_put(struct atrtp* atrtp)
    188 {
    189   if(!atrtp) return RES_BAD_ARG;
    190   ref_put(&atrtp->ref, release_atrtp);
    191   return RES_OK;
    192 }
    193 
    194 res_T
    195 atrtp_load(struct atrtp* atrtp, const char* path)
    196 {
    197   FILE* file = NULL;
    198   res_T res = RES_OK;
    199 
    200   if(!atrtp || !path) {
    201     res = RES_BAD_ARG;
    202     goto error;
    203   }
    204 
    205   file = fopen(path, "r");
    206   if(!file) {
    207     log_err(atrtp, "%s: error opening file `%s'.\n", FUNC_NAME, path);
    208     res = RES_IO_ERR;
    209     goto error;
    210   }
    211 
    212   res = load_stream(atrtp, file, path);
    213   if(res != RES_OK) goto error;
    214 
    215 exit:
    216   if(file) fclose(file);
    217   return res;
    218 error:
    219   goto exit;
    220 }
    221 
    222 res_T
    223 atrtp_load_stream
    224   (struct atrtp* atrtp,
    225    FILE* stream,
    226    const char* stream_name)
    227 {
    228   if(!atrtp || !stream) return RES_BAD_ARG;
    229   return load_stream(atrtp, stream, stream_name ? stream_name : "<stream>");
    230 }
    231 
    232 res_T
    233 atrtp_get_desc(const struct atrtp* atrtp, struct atrtp_desc* desc)
    234 {
    235   if(!atrtp || !desc) return RES_BAD_ARG;
    236   desc->properties = atrtp->props;
    237   desc->nnodes = (size_t)atrtp->nnodes;
    238   return RES_OK;
    239 }
    240