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-11-21 22:18:42 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             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : // This file contains the Virtual File Layer implementation that calls through
      14             : // to the VSI functions and should be included by HDF5 based drivers that wish
      15             : // to use the VFL for /vsi file system support.
      16             : 
      17             : #ifndef HDF5VFL_H_INCLUDED_
      18             : #define HDF5VFL_H_INCLUDED_
      19             : 
      20             : #include "cpl_port.h"
      21             : 
      22             : #include <algorithm>
      23             : #include <mutex>
      24             : 
      25             : #ifdef H5FD_FEAT_MEMMANAGE
      26             : #define HDF5_1_13_OR_LATER
      27             : #endif
      28             : 
      29             : // HDF5 >= 1.13.2
      30             : #ifdef H5FD_CLASS_VERSION
      31             : #if H5FD_CLASS_VERSION != 1
      32             : #error                                                                         \
      33             :     "HDF5_vsil_g needs to be adapted to the new layout of H5FD_class_t. Look at ${hdf5_prefix}/include/H5FDdevelop.h"
      34             : #endif
      35             : #endif
      36             : 
      37             : static std::mutex gMutex;
      38             : static hid_t hFileDriver = -1;
      39             : 
      40             : static H5FD_t *HDF5_vsil_open(const char *name, unsigned flags, hid_t fapl_id,
      41             :                               haddr_t maxaddr);
      42             : static herr_t HDF5_vsil_close(H5FD_t *_file);
      43             : static herr_t HDF5_vsil_query(const H5FD_t *_f1, unsigned long *flags);
      44             : static haddr_t HDF5_vsil_get_eoa(const H5FD_t *_file, H5FD_mem_t type);
      45             : static herr_t HDF5_vsil_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr);
      46             : static haddr_t HDF5_vsil_get_eof(const H5FD_t *_file, H5FD_mem_t type);
      47             : static herr_t HDF5_vsil_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id,
      48             :                              haddr_t addr, size_t size, void *buf);
      49             : static herr_t HDF5_vsil_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id,
      50             :                               haddr_t addr, size_t size, const void *buf);
      51             : static herr_t HDF5_vsil_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
      52             : 
      53             : static hid_t HDF5VFLGetFileDriver();
      54             : static void HDF5VFLUnloadFileDriver();
      55             : 
      56             : #define MAXADDR (((haddr_t)1 << (8 * sizeof(haddr_t) - 1)) - 1)
      57             : 
      58             : /* See https://support.hdfgroup.org/HDF5/doc/TechNotes/VFL.html */
      59             : static const H5FD_class_t HDF5_vsil_g = {
      60             : #ifdef H5FD_CLASS_VERSION
      61             :     H5FD_CLASS_VERSION,
      62             : #endif
      63             : #ifdef HDF5_1_13_OR_LATER
      64             :     /* value: 513 has been reserved with hdfgroup and is registered at:
      65             :      * https://portal.hdfgroup.org/pages/viewpage.action?pageId=74188097 */
      66             :     (H5FD_class_value_t)(513),
      67             : #endif
      68             :     "vsil",            /* name */
      69             :     MAXADDR,           /* maxaddr  */
      70             :     H5F_CLOSE_WEAK,    /* fc_degree  */
      71             :     nullptr,           /* terminate */
      72             :     nullptr,           /* sb_size  */
      73             :     nullptr,           /* sb_encode */
      74             :     nullptr,           /* sb_decode */
      75             :     0,                 /* fapl_size */
      76             :     nullptr,           /* fapl_get  */
      77             :     nullptr,           /* fapl_copy */
      78             :     nullptr,           /* fapl_free */
      79             :     0,                 /* dxpl_size */
      80             :     nullptr,           /* dxpl_copy */
      81             :     nullptr,           /* dxpl_free */
      82             :     HDF5_vsil_open,    /* open */
      83             :     HDF5_vsil_close,   /* close */
      84             :     nullptr,           /* cmp  */
      85             :     HDF5_vsil_query,   /* query */
      86             :     nullptr,           /* get_type_map */
      87             :     nullptr,           /* alloc */
      88             :     nullptr,           /* free */
      89             :     HDF5_vsil_get_eoa, /* get_eoa */
      90             :     HDF5_vsil_set_eoa, /* set_eoa */
      91             :     HDF5_vsil_get_eof, /* get_eof */
      92             :     nullptr,           /* get_handle */
      93             :     HDF5_vsil_read,    /* read */
      94             :     HDF5_vsil_write,   /* write */
      95             : #if H5FD_CLASS_VERSION == 1
      96             :     nullptr, /* read_vector */
      97             :     nullptr, /* write_vector */
      98             :     nullptr, /* read_selection */
      99             :     nullptr, /* write_selection */
     100             : #endif
     101             :     nullptr,            /* flush */
     102             :     HDF5_vsil_truncate, /* truncate */
     103             :     nullptr,            /* lock */
     104             :     nullptr,            /* unlock */
     105             : #ifdef HDF5_1_13_OR_LATER
     106             :     nullptr, /* del */
     107             :     nullptr, /* ctl */
     108             : #endif
     109             :     H5FD_FLMAP_DICHOTOMY /* fl_map */
     110             : };
     111             : 
     112             : typedef struct HDF5_vsil_t
     113             : {
     114             :     H5FD_t pub; /* must be first */
     115             :     VSILFILE *fp = nullptr;
     116             :     haddr_t eoa = 0;
     117             :     haddr_t eof = 0;
     118             : } HDF5_vsil_t;
     119             : 
     120         561 : static H5FD_t *HDF5_vsil_open(const char *name, unsigned flags,
     121             :                               hid_t /*fapl_id*/, haddr_t /*maxaddr*/)
     122             : {
     123         561 :     const char *openFlags = "rb";
     124         561 :     if ((H5F_ACC_RDWR & flags))
     125         174 :         openFlags = "rb+";
     126         561 :     if ((H5F_ACC_TRUNC & flags) || (H5F_ACC_CREAT & flags))
     127         121 :         openFlags = "wb+";
     128             : 
     129         561 :     VSILFILE *fp = VSIFOpenL(name, openFlags);
     130         561 :     if (!fp)
     131             :     {
     132           4 :         return nullptr;
     133             :     }
     134         557 :     if ((H5F_ACC_TRUNC & flags))
     135             :     {
     136         118 :         VSIFTruncateL(fp, 0);
     137             :     }
     138             : 
     139         557 :     HDF5_vsil_t *fh = new HDF5_vsil_t;
     140         557 :     memset(&fh->pub, 0, sizeof(fh->pub));
     141         557 :     if (!fh)
     142             :     {
     143           0 :         VSIFCloseL(fp);
     144           0 :         return nullptr;
     145             :     }
     146         557 :     fh->fp = fp;
     147             : 
     148         557 :     VSIFSeekL(fh->fp, 0, SEEK_END);
     149         557 :     fh->eof = static_cast<haddr_t>(VSIFTellL(fh->fp));
     150             : 
     151         557 :     return reinterpret_cast<H5FD_t *>(fh);
     152             : }
     153             : 
     154         557 : static herr_t HDF5_vsil_close(H5FD_t *_file)
     155             : {
     156         557 :     HDF5_vsil_t *fh = reinterpret_cast<HDF5_vsil_t *>(_file);
     157         557 :     int ret = VSIFCloseL(fh->fp);
     158         557 :     delete fh;
     159         557 :     return ret;
     160             : }
     161             : 
     162        1923 : static herr_t HDF5_vsil_query(const H5FD_t *, unsigned long *flags /* out */)
     163             : {
     164        1923 :     *flags = H5FD_FEAT_AGGREGATE_METADATA | H5FD_FEAT_ACCUMULATE_METADATA |
     165             :              H5FD_FEAT_DATA_SIEVE | H5FD_FEAT_AGGREGATE_SMALLDATA;
     166        1923 :     return 0;
     167             : }
     168             : 
     169       76992 : static haddr_t HDF5_vsil_get_eoa(const H5FD_t *_file, H5FD_mem_t /*type*/)
     170             : {
     171       76992 :     const HDF5_vsil_t *fh = reinterpret_cast<const HDF5_vsil_t *>(_file);
     172       76992 :     return fh->eoa;
     173             : }
     174             : 
     175        3923 : static herr_t HDF5_vsil_set_eoa(H5FD_t *_file, H5FD_mem_t /*type*/,
     176             :                                 haddr_t addr)
     177             : {
     178        3923 :     HDF5_vsil_t *fh = reinterpret_cast<HDF5_vsil_t *>(_file);
     179        3923 :     fh->eoa = addr;
     180        3923 :     return 0;
     181             : }
     182             : 
     183        1874 : static haddr_t HDF5_vsil_get_eof(const H5FD_t *_file, H5FD_mem_t /* type */
     184             : )
     185             : {
     186        1874 :     const HDF5_vsil_t *fh = reinterpret_cast<const HDF5_vsil_t *>(_file);
     187        1874 :     return fh->eof;
     188             : }
     189             : 
     190       24788 : static herr_t HDF5_vsil_read(H5FD_t *_file, H5FD_mem_t /* type */,
     191             :                              hid_t /* dxpl_id */, haddr_t addr, size_t size,
     192             :                              void *buf /*out*/)
     193             : {
     194       24788 :     HDF5_vsil_t *fh = reinterpret_cast<HDF5_vsil_t *>(_file);
     195       24788 :     VSIFSeekL(fh->fp, static_cast<vsi_l_offset>(addr), SEEK_SET);
     196       24788 :     return VSIFReadL(buf, size, 1, fh->fp) == 1 ? 0 : -1;
     197             : }
     198             : 
     199        4659 : static herr_t HDF5_vsil_write(H5FD_t *_file, H5FD_mem_t /* type */,
     200             :                               hid_t /* dxpl_id */, haddr_t addr, size_t size,
     201             :                               const void *buf /*out*/)
     202             : {
     203        4659 :     HDF5_vsil_t *fh = reinterpret_cast<HDF5_vsil_t *>(_file);
     204        4659 :     VSIFSeekL(fh->fp, static_cast<vsi_l_offset>(addr), SEEK_SET);
     205        4659 :     int ret = VSIFWriteL(buf, size, 1, fh->fp) == 1 ? 0 : -1;
     206        4659 :     fh->eof = std::max(fh->eof, static_cast<haddr_t>(VSIFTellL(fh->fp)));
     207        4659 :     return ret;
     208             : }
     209             : 
     210         902 : static herr_t HDF5_vsil_truncate(H5FD_t *_file, hid_t /* dxpl_id*/,
     211             :                                  hbool_t /*closing*/)
     212             : {
     213         902 :     HDF5_vsil_t *fh = reinterpret_cast<HDF5_vsil_t *>(_file);
     214         902 :     if (fh->eoa != fh->eof)
     215             :     {
     216           4 :         if (VSIFTruncateL(fh->fp, fh->eoa) < 0)
     217             :         {
     218           0 :             return -1;
     219             :         }
     220           4 :         fh->eof = fh->eoa;
     221             :     }
     222         902 :     return 0;
     223             : }
     224             : 
     225             : /************************************************************************/
     226             : /*                       HDF5VFLGetFileDriver()                         */
     227             : /************************************************************************/
     228             : 
     229         413 : static hid_t HDF5VFLGetFileDriver()
     230             : {
     231         413 :     std::lock_guard<std::mutex> oLock(gMutex);
     232         413 :     if (hFileDriver < 0)
     233             :     {
     234           4 :         hFileDriver = H5FDregister(&HDF5_vsil_g);
     235             : #if H5E_auto_t_vers == 2
     236             :         // also, don't print error messages from KEA driver.
     237             :         // (which uses H5E_auto_t_vers=2 - the default, hdf uses 1 for some
     238             :         // reason). These tend to be meaningless - ie no GCP's found etc. They
     239             :         // didn't seem to be shown when we didn't use the VFL layer
     240             :         // - maybe VFL turns them on?
     241           1 :         H5Eset_auto(H5E_DEFAULT, nullptr, nullptr);
     242             : #endif
     243             :     }
     244         826 :     return hFileDriver;
     245             : }
     246             : 
     247             : /************************************************************************/
     248             : /*                     HDF5VFLUnloadFileDriver()                        */
     249             : /************************************************************************/
     250             : 
     251          41 : static void HDF5VFLUnloadFileDriver()
     252             : {
     253             :     {
     254          82 :         std::lock_guard<std::mutex> oLock(gMutex);
     255          41 :         if (hFileDriver >= 0)
     256             :         {
     257           1 :             H5FDunregister(hFileDriver);
     258           1 :             hFileDriver = -1;
     259             :         }
     260             :     }
     261          41 : }
     262             : 
     263             : #endif /* HDF5VFL_H_INCLUDED_ */

Generated by: LCOV version 1.14