LCOV - code coverage report
Current view: top level - frmts/hdf5 - hdf5vfl.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 64 67 95.5 %
Date: 2024-05-03 15:49:35 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  Hierarchical Data Format Release 5 (HDF5)
       4             :  * Authors:  Denis Nadeau <denis.nadeau@gmail.com>
       5             :  *           Sam Gillingham <gillingham.sam@gmail.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2008-2018, Even Rouault <even.rouault at spatialys.com>
       9             :  *
      10             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  ****************************************************************************/
      28             : 
      29             : // This file contains the Virtual File Layer implementation that calls through
      30             : // to the VSI functions and should be included by HDF5 based drivers that wish
      31             : // to use the VFL for /vsi file system support.
      32             : 
      33             : #ifndef HDF5VFL_H_INCLUDED_
      34             : #define HDF5VFL_H_INCLUDED_
      35             : 
      36             : #include "cpl_port.h"
      37             : 
      38             : #include <algorithm>
      39             : #include <mutex>
      40             : 
      41             : #ifdef H5FD_FEAT_MEMMANAGE
      42             : #define HDF5_1_13_OR_LATER
      43             : #endif
      44             : 
      45             : // HDF5 >= 1.13.2
      46             : #ifdef H5FD_CLASS_VERSION
      47             : #if H5FD_CLASS_VERSION != 1
      48             : #error                                                                         \
      49             :     "HDF5_vsil_g needs to be adapted to the new layout of H5FD_class_t. Look at ${hdf5_prefix}/include/H5FDdevelop.h"
      50             : #endif
      51             : #endif
      52             : 
      53             : static std::mutex gMutex;
      54             : static hid_t hFileDriver = -1;
      55             : 
      56             : static H5FD_t *HDF5_vsil_open(const char *name, unsigned flags, hid_t fapl_id,
      57             :                               haddr_t maxaddr);
      58             : static herr_t HDF5_vsil_close(H5FD_t *_file);
      59             : static herr_t HDF5_vsil_query(const H5FD_t *_f1, unsigned long *flags);
      60             : static haddr_t HDF5_vsil_get_eoa(const H5FD_t *_file, H5FD_mem_t type);
      61             : static herr_t HDF5_vsil_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr);
      62             : static haddr_t HDF5_vsil_get_eof(const H5FD_t *_file, H5FD_mem_t type);
      63             : static herr_t HDF5_vsil_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id,
      64             :                              haddr_t addr, size_t size, void *buf);
      65             : static herr_t HDF5_vsil_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id,
      66             :                               haddr_t addr, size_t size, const void *buf);
      67             : static herr_t HDF5_vsil_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
      68             : 
      69             : static hid_t HDF5VFLGetFileDriver();
      70             : static void HDF5VFLUnloadFileDriver();
      71             : 
      72             : #define MAXADDR (((haddr_t)1 << (8 * sizeof(haddr_t) - 1)) - 1)
      73             : 
      74             : /* See https://support.hdfgroup.org/HDF5/doc/TechNotes/VFL.html */
      75             : static const H5FD_class_t HDF5_vsil_g = {
      76             : #ifdef H5FD_CLASS_VERSION
      77             :     H5FD_CLASS_VERSION,
      78             : #endif
      79             : #ifdef HDF5_1_13_OR_LATER
      80             :     /* value: 513 has been reserved with hdfgroup and is registered at:
      81             :      * https://portal.hdfgroup.org/pages/viewpage.action?pageId=74188097 */
      82             :     (H5FD_class_value_t)(513),
      83             : #endif
      84             :     "vsil",            /* name */
      85             :     MAXADDR,           /* maxaddr  */
      86             :     H5F_CLOSE_WEAK,    /* fc_degree  */
      87             :     nullptr,           /* terminate */
      88             :     nullptr,           /* sb_size  */
      89             :     nullptr,           /* sb_encode */
      90             :     nullptr,           /* sb_decode */
      91             :     0,                 /* fapl_size */
      92             :     nullptr,           /* fapl_get  */
      93             :     nullptr,           /* fapl_copy */
      94             :     nullptr,           /* fapl_free */
      95             :     0,                 /* dxpl_size */
      96             :     nullptr,           /* dxpl_copy */
      97             :     nullptr,           /* dxpl_free */
      98             :     HDF5_vsil_open,    /* open */
      99             :     HDF5_vsil_close,   /* close */
     100             :     nullptr,           /* cmp  */
     101             :     HDF5_vsil_query,   /* query */
     102             :     nullptr,           /* get_type_map */
     103             :     nullptr,           /* alloc */
     104             :     nullptr,           /* free */
     105             :     HDF5_vsil_get_eoa, /* get_eoa */
     106             :     HDF5_vsil_set_eoa, /* set_eoa */
     107             :     HDF5_vsil_get_eof, /* get_eof */
     108             :     nullptr,           /* get_handle */
     109             :     HDF5_vsil_read,    /* read */
     110             :     HDF5_vsil_write,   /* write */
     111             : #if H5FD_CLASS_VERSION == 1
     112             :     nullptr, /* read_vector */
     113             :     nullptr, /* write_vector */
     114             :     nullptr, /* read_selection */
     115             :     nullptr, /* write_selection */
     116             : #endif
     117             :     nullptr,            /* flush */
     118             :     HDF5_vsil_truncate, /* truncate */
     119             :     nullptr,            /* lock */
     120             :     nullptr,            /* unlock */
     121             : #ifdef HDF5_1_13_OR_LATER
     122             :     nullptr, /* del */
     123             :     nullptr, /* ctl */
     124             : #endif
     125             :     H5FD_FLMAP_DICHOTOMY /* fl_map */
     126             : };
     127             : 
     128             : typedef struct HDF5_vsil_t
     129             : {
     130             :     H5FD_t pub; /* must be first */
     131             :     VSILFILE *fp = nullptr;
     132             :     haddr_t eoa = 0;
     133             :     haddr_t eof = 0;
     134             : } HDF5_vsil_t;
     135             : 
     136         544 : static H5FD_t *HDF5_vsil_open(const char *name, unsigned flags,
     137             :                               hid_t /*fapl_id*/, haddr_t /*maxaddr*/)
     138             : {
     139         544 :     const char *openFlags = "rb";
     140         544 :     if ((H5F_ACC_RDWR & flags))
     141         174 :         openFlags = "rb+";
     142         544 :     if ((H5F_ACC_TRUNC & flags) || (H5F_ACC_CREAT & flags))
     143         121 :         openFlags = "wb+";
     144             : 
     145         544 :     VSILFILE *fp = VSIFOpenL(name, openFlags);
     146         544 :     if (!fp)
     147             :     {
     148           4 :         return nullptr;
     149             :     }
     150         540 :     if ((H5F_ACC_TRUNC & flags))
     151             :     {
     152         118 :         VSIFTruncateL(fp, 0);
     153             :     }
     154             : 
     155         540 :     HDF5_vsil_t *fh = new HDF5_vsil_t;
     156         540 :     memset(&fh->pub, 0, sizeof(fh->pub));
     157         540 :     if (!fh)
     158             :     {
     159           0 :         VSIFCloseL(fp);
     160           0 :         return nullptr;
     161             :     }
     162         540 :     fh->fp = fp;
     163             : 
     164         540 :     VSIFSeekL(fh->fp, 0, SEEK_END);
     165         540 :     fh->eof = static_cast<haddr_t>(VSIFTellL(fh->fp));
     166             : 
     167         540 :     return reinterpret_cast<H5FD_t *>(fh);
     168             : }
     169             : 
     170         540 : static herr_t HDF5_vsil_close(H5FD_t *_file)
     171             : {
     172         540 :     HDF5_vsil_t *fh = reinterpret_cast<HDF5_vsil_t *>(_file);
     173         540 :     int ret = VSIFCloseL(fh->fp);
     174         540 :     delete fh;
     175         540 :     return ret;
     176             : }
     177             : 
     178        1889 : static herr_t HDF5_vsil_query(const H5FD_t *, unsigned long *flags /* out */)
     179             : {
     180        1889 :     *flags = H5FD_FEAT_AGGREGATE_METADATA | H5FD_FEAT_ACCUMULATE_METADATA |
     181             :              H5FD_FEAT_DATA_SIEVE | H5FD_FEAT_AGGREGATE_SMALLDATA;
     182        1889 :     return 0;
     183             : }
     184             : 
     185       76118 : static haddr_t HDF5_vsil_get_eoa(const H5FD_t *_file, H5FD_mem_t /*type*/)
     186             : {
     187       76118 :     const HDF5_vsil_t *fh = reinterpret_cast<const HDF5_vsil_t *>(_file);
     188       76118 :     return fh->eoa;
     189             : }
     190             : 
     191        3847 : static herr_t HDF5_vsil_set_eoa(H5FD_t *_file, H5FD_mem_t /*type*/,
     192             :                                 haddr_t addr)
     193             : {
     194        3847 :     HDF5_vsil_t *fh = reinterpret_cast<HDF5_vsil_t *>(_file);
     195        3847 :     fh->eoa = addr;
     196        3847 :     return 0;
     197             : }
     198             : 
     199        1806 : static haddr_t HDF5_vsil_get_eof(const H5FD_t *_file, H5FD_mem_t /* type */
     200             : )
     201             : {
     202        1806 :     const HDF5_vsil_t *fh = reinterpret_cast<const HDF5_vsil_t *>(_file);
     203        1806 :     return fh->eof;
     204             : }
     205             : 
     206       24327 : static herr_t HDF5_vsil_read(H5FD_t *_file, H5FD_mem_t /* type */,
     207             :                              hid_t /* dxpl_id */, haddr_t addr, size_t size,
     208             :                              void *buf /*out*/)
     209             : {
     210       24327 :     HDF5_vsil_t *fh = reinterpret_cast<HDF5_vsil_t *>(_file);
     211       24327 :     VSIFSeekL(fh->fp, static_cast<vsi_l_offset>(addr), SEEK_SET);
     212       24327 :     return VSIFReadL(buf, size, 1, fh->fp) == 1 ? 0 : -1;
     213             : }
     214             : 
     215        4659 : static herr_t HDF5_vsil_write(H5FD_t *_file, H5FD_mem_t /* type */,
     216             :                               hid_t /* dxpl_id */, haddr_t addr, size_t size,
     217             :                               const void *buf /*out*/)
     218             : {
     219        4659 :     HDF5_vsil_t *fh = reinterpret_cast<HDF5_vsil_t *>(_file);
     220        4659 :     VSIFSeekL(fh->fp, static_cast<vsi_l_offset>(addr), SEEK_SET);
     221        4659 :     int ret = VSIFWriteL(buf, size, 1, fh->fp) == 1 ? 0 : -1;
     222        4659 :     fh->eof = std::max(fh->eof, static_cast<haddr_t>(VSIFTellL(fh->fp)));
     223        4659 :     return ret;
     224             : }
     225             : 
     226         902 : static herr_t HDF5_vsil_truncate(H5FD_t *_file, hid_t /* dxpl_id*/,
     227             :                                  hbool_t /*closing*/)
     228             : {
     229         902 :     HDF5_vsil_t *fh = reinterpret_cast<HDF5_vsil_t *>(_file);
     230         902 :     if (fh->eoa != fh->eof)
     231             :     {
     232           4 :         if (VSIFTruncateL(fh->fp, fh->eoa) < 0)
     233             :         {
     234           0 :             return -1;
     235             :         }
     236           4 :         fh->eof = fh->eoa;
     237             :     }
     238         902 :     return 0;
     239             : }
     240             : 
     241             : /************************************************************************/
     242             : /*                       HDF5VFLGetFileDriver()                         */
     243             : /************************************************************************/
     244             : 
     245         396 : static hid_t HDF5VFLGetFileDriver()
     246             : {
     247         396 :     std::lock_guard<std::mutex> oLock(gMutex);
     248         396 :     if (hFileDriver < 0)
     249             :     {
     250           4 :         hFileDriver = H5FDregister(&HDF5_vsil_g);
     251             : #if H5E_auto_t_vers == 2
     252             :         // also, don't print error messages from KEA driver.
     253             :         // (which uses H5E_auto_t_vers=2 - the default, hdf uses 1 for some
     254             :         // reason). These tend to be meaningless - ie no GCP's found etc. They
     255             :         // didn't seem to be shown when we didn't use the VFL layer
     256             :         // - maybe VFL turns them on?
     257           1 :         H5Eset_auto(H5E_DEFAULT, nullptr, nullptr);
     258             : #endif
     259             :     }
     260         792 :     return hFileDriver;
     261             : }
     262             : 
     263             : /************************************************************************/
     264             : /*                     HDF5VFLUnloadFileDriver()                        */
     265             : /************************************************************************/
     266             : 
     267          34 : static void HDF5VFLUnloadFileDriver()
     268             : {
     269             :     {
     270          68 :         std::lock_guard<std::mutex> oLock(gMutex);
     271          34 :         if (hFileDriver >= 0)
     272             :         {
     273           1 :             H5FDunregister(hFileDriver);
     274           1 :             hFileDriver = -1;
     275             :         }
     276             :     }
     277          34 : }
     278             : 
     279             : #endif /* HDF5VFL_H_INCLUDED_ */

Generated by: LCOV version 1.14