/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright by The HDF Group.                                               *
 * All rights reserved.                                                      *
 *                                                                           *
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
 * terms governing use, modification, and redistribution, is contained in    *
 * the LICENSE file, which can be found at the root of the source code       *
 * distribution tree, or in https://www.hdfgroup.org/licenses.               *
 * If you do not have access to either file, you may request a copy from     *
 * help@hdfgroup.org.                                                        *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#if !(defined(H5FA_FRIEND) | defined(H5FA_MODULE))
#error "Do not include this file outside the H5FA package!"
#endif

#ifndef H5FApkg_H
#define H5FApkg_H

#include "H5FAprivate.h"

#include "H5ACprivate.h" 
#include "H5FLprivate.h" 

#ifdef H5FA_TESTING
#define H5FA_TEST_FILL ((uint64_t)ULLONG_MAX)
#endif 

#define H5FA_SIZEOF_CHKSUM 4

#define H5FA_METADATA_PREFIX_SIZE(c)                                                                         \
    (H5_SIZEOF_MAGIC                                                               \
     + 1                                                                           \
     + 1                                                                           \
     + ((c) ? H5FA_SIZEOF_CHKSUM : 0)                                              \
    )

#define H5FA_HEADER_SIZE(sizeof_addr, sizeof_size)                                                           \
    (                                                                           \
     H5FA_METADATA_PREFIX_SIZE(true)                                                                         \
                                                                                                             \
                                                                              \
     + 1                                                                                   \
     + 1                                                                             \
                                                                                                             \
                                                                          \
     + (sizeof_size)                                                   \
                                                                                                             \
                                                                     \
     + (sizeof_addr)                                             \
    )

#define H5FA_HEADER_SIZE_FILE(f) (H5FA_HEADER_SIZE(H5F_SIZEOF_ADDR(f), H5F_SIZEOF_SIZE(f)))

#define H5FA_HEADER_SIZE_HDR(h) (H5FA_HEADER_SIZE((h)->sizeof_addr, (h)->sizeof_size))

#define H5FA_DBLOCK_PREFIX_SIZE(d)                                                                           \
    (                                                                           \
     H5FA_METADATA_PREFIX_SIZE(true)                                                                         \
                                                                                                             \
                                                                                 \
     + (d)->hdr->sizeof_addr                   \
                                                                                                             \
                                                                 \
     + (d)->dblk_page_init_size      \
    )

#define H5FA_DBLOCK_SIZE(d)                                                                                  \
    (                                                                           \
     H5FA_DBLOCK_PREFIX_SIZE(d)                                                                              \
                                                                                                             \
                                                                  \
     + ((d)->hdr->cparam.nelmts * (size_t)(d)->hdr->cparam.raw_elmt_size) +                                  \
     ((d)->npages * H5FA_SIZEOF_CHKSUM)                                                        \
    )

#define H5FA_DBLK_PAGE_SIZE(h, nelmts)                                                                       \
    (                                                                       \
     +(nelmts * (size_t)(h)->cparam.raw_elmt_size)                          \
     + H5FA_SIZEOF_CHKSUM                                                        \
    )

typedef struct H5FA_hdr_t {
    
    H5AC_info_t cache_info;

    
    H5FA_create_t cparam; 

    
    haddr_t dblk_addr; 

    
    H5FA_stat_t stats; 

    
    size_t  rc;             
    haddr_t addr;           
    size_t  size;           
    H5F_t  *f;              
    size_t  file_rc;        
    bool    pending_delete; 
    size_t  sizeof_addr;    
    size_t  sizeof_size;    

    
    void *cb_ctx; 

    
    bool                swmr_write; 
    H5AC_proxy_entry_t *top_proxy;  
    void               *parent;     
} H5FA_hdr_t;

typedef struct H5FA_dblock_t {
    
    H5AC_info_t cache_info;

    
    uint8_t *dblk_page_init; 
    void    *elmts;          

    
    H5FA_hdr_t *hdr; 

    
    H5AC_proxy_entry_t *top_proxy; 

    
    haddr_t addr;             
    hsize_t size;             
    size_t  npages;           
    size_t  last_page_nelmts; 

    
    size_t dblk_page_nelmts;    
    size_t dblk_page_size;      
    size_t dblk_page_init_size; 
} H5FA_dblock_t;

typedef struct H5FA_dbk_page_t {
    
    H5AC_info_t cache_info;

    
    void *elmts; 

    
    H5FA_hdr_t *hdr; 

    
    H5AC_proxy_entry_t *top_proxy; 

    
    haddr_t addr;   
    size_t  size;   
    size_t  nelmts; 
} H5FA_dblk_page_t;

struct H5FA_t {
    H5FA_hdr_t *hdr; 
    H5F_t      *f;   
};

typedef struct H5FA_hdr_cache_ud_t {
    H5F_t  *f;         
    haddr_t addr;      
    void   *ctx_udata; 
} H5FA_hdr_cache_ud_t;

typedef struct H5FA_dblock_cache_ud_t {
    H5FA_hdr_t *hdr;       
    haddr_t     dblk_addr; 
} H5FA_dblock_cache_ud_t;

typedef struct H5FA_dblk_page_cache_ud_t {
    H5FA_hdr_t *hdr;            
    size_t      nelmts;         
    haddr_t     dblk_page_addr; 
} H5FA_dblk_page_cache_ud_t;

H5_DLLVAR const H5FA_class_t H5FA_CLS_TEST[1];

H5_DLLVAR const H5FA_class_t *const H5FA_client_class_g[H5FA_NUM_CLS_ID];

H5_DLL herr_t H5FA__create_flush_depend(H5AC_info_t *parent_entry, H5AC_info_t *child_entry);
H5_DLL herr_t H5FA__destroy_flush_depend(H5AC_info_t *parent_entry, H5AC_info_t *child_entry);

H5_DLL H5FA_hdr_t *H5FA__hdr_alloc(H5F_t *f);
H5_DLL herr_t      H5FA__hdr_init(H5FA_hdr_t *hdr, void *ctx_udata);
H5_DLL haddr_t     H5FA__hdr_create(H5F_t *f, const H5FA_create_t *cparam, void *ctx_udata);
H5_DLL void       *H5FA__hdr_alloc_elmts(H5FA_hdr_t *hdr, size_t nelmts);
H5_DLL herr_t      H5FA__hdr_free_elmts(H5FA_hdr_t *hdr, size_t nelmts, void *elmts);
H5_DLL herr_t      H5FA__hdr_incr(H5FA_hdr_t *hdr);
H5_DLL herr_t      H5FA__hdr_decr(H5FA_hdr_t *hdr);
H5_DLL herr_t      H5FA__hdr_fuse_incr(H5FA_hdr_t *hdr);
H5_DLL size_t      H5FA__hdr_fuse_decr(H5FA_hdr_t *hdr);
H5_DLL herr_t      H5FA__hdr_modified(H5FA_hdr_t *hdr);
H5_DLL H5FA_hdr_t *H5FA__hdr_protect(H5F_t *f, haddr_t fa_addr, void *ctx_udata, unsigned flags);
H5_DLL herr_t      H5FA__hdr_unprotect(H5FA_hdr_t *hdr, unsigned cache_flags);
H5_DLL herr_t      H5FA__hdr_delete(H5FA_hdr_t *hdr);
H5_DLL herr_t      H5FA__hdr_dest(H5FA_hdr_t *hdr);

H5_DLL H5FA_dblock_t *H5FA__dblock_alloc(H5FA_hdr_t *hdr);
H5_DLL haddr_t        H5FA__dblock_create(H5FA_hdr_t *hdr, bool *hdr_dirty);
H5_DLL unsigned       H5FA__dblock_sblk_idx(const H5FA_hdr_t *hdr, hsize_t idx);
H5_DLL H5FA_dblock_t *H5FA__dblock_protect(H5FA_hdr_t *hdr, haddr_t dblk_addr, unsigned flags);
H5_DLL herr_t         H5FA__dblock_unprotect(H5FA_dblock_t *dblock, unsigned cache_flags);
H5_DLL herr_t         H5FA__dblock_delete(H5FA_hdr_t *hdr, haddr_t dblk_addr);
H5_DLL herr_t         H5FA__dblock_dest(H5FA_dblock_t *dblock);

H5_DLL herr_t            H5FA__dblk_page_create(H5FA_hdr_t *hdr, haddr_t addr, size_t nelmts);
H5_DLL H5FA_dblk_page_t *H5FA__dblk_page_alloc(H5FA_hdr_t *hdr, size_t nelmts);
H5_DLL H5FA_dblk_page_t *H5FA__dblk_page_protect(H5FA_hdr_t *hdr, haddr_t dblk_page_addr,
                                                 size_t dblk_page_nelmts, unsigned flags);
H5_DLL herr_t            H5FA__dblk_page_unprotect(H5FA_dblk_page_t *dblk_page, unsigned cache_flags);
H5_DLL herr_t            H5FA__dblk_page_dest(H5FA_dblk_page_t *dblk_page);

H5_DLL herr_t H5FA__hdr_debug(H5F_t *f, haddr_t addr, FILE *stream, int indent, int fwidth,
                              const H5FA_class_t *cls, haddr_t obj_addr);
H5_DLL herr_t H5FA__dblock_debug(H5F_t *f, haddr_t addr, FILE *stream, int indent, int fwidth,
                                 const H5FA_class_t *cls, haddr_t hdr_addr, haddr_t obj_addr);

#ifdef H5FA_TESTING
H5_DLL herr_t H5FA__get_cparam_test(const H5FA_t *ea, H5FA_create_t *cparam);
H5_DLL int    H5FA__cmp_cparam_test(const H5FA_create_t *cparam1, const H5FA_create_t *cparam2);
#endif 

#endif 
