/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * 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(H5EA_FRIEND) | defined(H5EA_MODULE))
#error "Do not include this file outside the H5EA package!"
#endif

#ifndef H5EApkg_H
#define H5EApkg_H

#include "H5EAprivate.h"

#include "H5FLprivate.h" 
#include "H5VMprivate.h" 

#ifdef H5EA_TESTING
#define H5EA_TEST_FILL ((uint64_t)ULLONG_MAX)
#endif 

#define H5EA_SIZEOF_CHKSUM 4

#define H5EA_METADATA_PREFIX_SIZE(c)                                                                         \
    (H5_SIZEOF_MAGIC                                                                          \
     + 1                                                                                        \
     + 1                                                                                     \
     + ((c) ? H5EA_SIZEOF_CHKSUM : 0)                                                 \
    )

#define H5EA_HEADER_SIZE(sizeof_addr, sizeof_size)                                                           \
    (                                                                           \
     H5EA_METADATA_PREFIX_SIZE(true)                                                                         \
                                                                                                             \
                                                                              \
     + 1                                                                                   \
     + 1                                                                        \
     + 1                                                          \
     + 1                                                                 \
     + 1                                                \
     + 1                                                                             \
                                                                                                             \
                                                                     \
     + (sizeof_size)                                                     \
     + (sizeof_size)                                                       \
     + (sizeof_size)                                                      \
     + (sizeof_size)                                                        \
     + (sizeof_size)                                                                     \
     + (sizeof_size)                                                      \
                                                                                                             \
                                                                \
     + (sizeof_addr)                                                        \
    )

#define H5EA_HEADER_SIZE_FILE(f) (H5EA_HEADER_SIZE(H5F_SIZEOF_ADDR(f), H5F_SIZEOF_SIZE(f)))

#define H5EA_HEADER_SIZE_HDR(h) (H5EA_HEADER_SIZE((h)->sizeof_addr, (h)->sizeof_size))

#define H5EA_IBLOCK_SIZE(i)                                                                                  \
    (                                                                           \
     H5EA_METADATA_PREFIX_SIZE(true)                                                                         \
                                                                                                             \
                                                                                 \
     + (i)->hdr->sizeof_addr                                     \
                                                                                                             \
                                                           \
     + ((size_t)(i)->hdr->cparam.idx_blk_elmts *                                                             \
        (size_t)(i)->hdr->cparam.raw_elmt_size)                                \
     + ((i)->ndblk_addrs * (i)->hdr->sizeof_addr)                  \
     + ((i)->nsblk_addrs * (i)->hdr->sizeof_addr)                 \
    )

#define H5EA_SBLOCK_SIZE(s)                                                                                  \
    (                                                                           \
     H5EA_METADATA_PREFIX_SIZE(true)                                                                         \
                                                                                                             \
                                                                                 \
     + (s)->hdr->sizeof_addr                                     \
     + (s)->hdr->arr_off_size                                          \
                                                                                                             \
                                                           \
     +                                                                                                       \
     ((s)->ndblks *                                                                                          \
      (s)->dblk_page_init_size)   \
     + ((s)->ndblks * (s)->hdr->sizeof_addr)                       \
    )

#define H5EA_DBLOCK_PREFIX_SIZE(d)                                                                           \
    (                                                                           \
     H5EA_METADATA_PREFIX_SIZE(true)                                                                         \
                                                                                                             \
                                                                                 \
     + (d)->hdr->sizeof_addr                                     \
     + (d)->hdr->arr_off_size                                          \
    )

#define H5EA_DBLOCK_SIZE(d)                                                                                  \
    (                                                                           \
     H5EA_DBLOCK_PREFIX_SIZE(d)                                                                              \
                                                                                                             \
                                                            \
     + ((d)->nelmts * (size_t)(d)->hdr->cparam.raw_elmt_size)                   \
     + ((d)->npages * H5EA_SIZEOF_CHKSUM)                                        \
    )

#define H5EA_DBLK_PAGE_SIZE(h)                                                                               \
    (+((h)->dblk_page_nelmts * (size_t)(h)->cparam.raw_elmt_size)           \
     + H5EA_SIZEOF_CHKSUM                                                        \
    )

#define H5EA_SIZEOF_OFFSET_BITS(b) (((b) + 7) / 8)

#define H5EA_SBLK_FIRST_IDX(m) (2 * H5VM_log2_of2((uint32_t)m))

typedef struct H5EA_sblk_info_t {
    size_t  ndblks;      
    size_t  dblk_nelmts; 
    hsize_t start_idx;   
    hsize_t start_dblk;  
} H5EA_sblk_info_t;

typedef struct H5EA_hdr_t {
    
    H5AC_info_t cache_info;

    
    H5EA_create_t cparam; 

    
    haddr_t idx_blk_addr; 

    
    
    H5EA_stat_t stats; 

    
    struct {
        size_t            nalloc; 
        H5FL_fac_head_t **fac;    
    } elmt_fac;

    
    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;    
    unsigned char arr_off_size;   

    
    size_t            nsblks;    
    H5EA_sblk_info_t *sblk_info; 

    
    size_t dblk_page_nelmts; 

    
    void *cb_ctx; 

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

typedef struct H5EA_iblock_t {
    
    H5AC_info_t cache_info;

    
    void    *elmts;      
    haddr_t *dblk_addrs; 
    haddr_t *sblk_addrs; 

    
    H5EA_hdr_t *hdr;  
    haddr_t     addr; 
    size_t      size; 

    
    H5AC_proxy_entry_t *top_proxy; 

    
    size_t nsblks;      
    size_t ndblk_addrs; 
    size_t nsblk_addrs; 
} H5EA_iblock_t;

typedef struct H5EA_sblock_t {
    
    H5AC_info_t cache_info;

    
    hsize_t  block_off;  
    haddr_t *dblk_addrs; 
    uint8_t *page_init;  

    
    H5EA_hdr_t *hdr;  
    haddr_t     addr; 
    size_t      size; 

    
    bool                has_hdr_depend; 
    H5AC_proxy_entry_t *top_proxy;      
    H5EA_iblock_t      *parent;         

    
    unsigned idx;                 
    size_t   ndblks;              
    size_t   dblk_nelmts;         
    size_t   dblk_npages;         
    size_t   dblk_page_init_size; 
    size_t   dblk_page_size;      
} H5EA_sblock_t;

typedef struct H5EA_dblock_t {
    
    H5AC_info_t cache_info;

    
    hsize_t block_off; 
    void   *elmts;     

    
    H5EA_hdr_t *hdr;  
    haddr_t     addr; 
    size_t      size; 

    
    bool                has_hdr_depend; 
    H5AC_proxy_entry_t *top_proxy;      
    void               *parent;         

    
    size_t nelmts; 
    size_t npages; 
} H5EA_dblock_t;

typedef struct H5EA_dbk_page_t {
    
    H5AC_info_t cache_info;

    
    void *elmts; 

    
    H5EA_hdr_t *hdr;  
    haddr_t     addr; 
    size_t      size; 

    
    bool                has_hdr_depend; 
    H5AC_proxy_entry_t *top_proxy;      
    H5EA_sblock_t      *parent;         

    
    
} H5EA_dblk_page_t;

struct H5EA_t {
    H5EA_hdr_t *hdr; 
    H5F_t      *f;   
};

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

typedef struct H5EA_sblock_cache_ud_t {
    H5EA_hdr_t    *hdr;       
    H5EA_iblock_t *parent;    
    unsigned       sblk_idx;  
    haddr_t        sblk_addr; 
} H5EA_sblock_cache_ud_t;

typedef struct H5EA_dblock_cache_ud_t {
    H5EA_hdr_t *hdr;       
    void       *parent;    
    size_t      nelmts;    
    haddr_t     dblk_addr; 
} H5EA_dblock_cache_ud_t;

typedef struct H5EA_dblk_page_cache_ud_t {
    H5EA_hdr_t    *hdr;            
    H5EA_sblock_t *parent;         
    haddr_t        dblk_page_addr; 
} H5EA_dblk_page_cache_ud_t;

#ifdef H5EA_TESTING
typedef struct H5EA__ctx_cb_t {
    herr_t (*encode)(const void *elmt, size_t nelmts, void *udata); 
    void *udata;                                                    
} H5EA__ctx_cb_t;
#endif 

H5_DLLVAR const H5EA_class_t H5EA_CLS_TEST[1];

H5_DLLVAR const H5EA_class_t *const H5EA_client_class_g[H5EA_NUM_CLS_ID];

H5_DLL herr_t H5EA__create_flush_depend(H5AC_info_t *parent_entry, H5AC_info_t *child_entry);
H5_DLL herr_t H5EA__destroy_flush_depend(H5AC_info_t *parent_entry, H5AC_info_t *child_entry);

H5_DLL H5EA_hdr_t *H5EA__hdr_alloc(H5F_t *f);
H5_DLL herr_t      H5EA__hdr_init(H5EA_hdr_t *hdr, void *ctx_udata);
H5_DLL haddr_t     H5EA__hdr_create(H5F_t *f, const H5EA_create_t *cparam, void *ctx_udata);
H5_DLL void       *H5EA__hdr_alloc_elmts(H5EA_hdr_t *hdr, size_t nelmts) H5_ATTR_MALLOC;
H5_DLL herr_t      H5EA__hdr_free_elmts(H5EA_hdr_t *hdr, size_t nelmts, void *elmts);
H5_DLL herr_t      H5EA__hdr_incr(H5EA_hdr_t *hdr);
H5_DLL herr_t      H5EA__hdr_decr(H5EA_hdr_t *hdr);
H5_DLL herr_t      H5EA__hdr_fuse_incr(H5EA_hdr_t *hdr);
H5_DLL size_t      H5EA__hdr_fuse_decr(H5EA_hdr_t *hdr);
H5_DLL herr_t      H5EA__hdr_modified(H5EA_hdr_t *hdr);
H5_DLL H5EA_hdr_t *H5EA__hdr_protect(H5F_t *f, haddr_t ea_addr, void *ctx_udata, unsigned flags);
H5_DLL herr_t      H5EA__hdr_unprotect(H5EA_hdr_t *hdr, unsigned cache_flags);
H5_DLL herr_t      H5EA__hdr_delete(H5EA_hdr_t *hdr);
H5_DLL herr_t      H5EA__hdr_dest(H5EA_hdr_t *hdr);

H5_DLL H5EA_iblock_t *H5EA__iblock_alloc(H5EA_hdr_t *hdr);
H5_DLL haddr_t        H5EA__iblock_create(H5EA_hdr_t *hdr, bool *stats_changed);
H5_DLL H5EA_iblock_t *H5EA__iblock_protect(H5EA_hdr_t *hdr, unsigned flags);
H5_DLL herr_t         H5EA__iblock_unprotect(H5EA_iblock_t *iblock, unsigned cache_flags);
H5_DLL herr_t         H5EA__iblock_delete(H5EA_hdr_t *hdr);
H5_DLL herr_t         H5EA__iblock_dest(H5EA_iblock_t *iblock);

H5_DLL H5EA_sblock_t *H5EA__sblock_alloc(H5EA_hdr_t *hdr, H5EA_iblock_t *parent, unsigned sblk_idx);
H5_DLL haddr_t        H5EA__sblock_create(H5EA_hdr_t *hdr, H5EA_iblock_t *parent, bool *stats_changed,
                                          unsigned sblk_idx);
H5_DLL H5EA_sblock_t *H5EA__sblock_protect(H5EA_hdr_t *hdr, H5EA_iblock_t *parent, haddr_t sblk_addr,
                                           unsigned sblk_idx, unsigned flags);
H5_DLL herr_t         H5EA__sblock_unprotect(H5EA_sblock_t *sblock, unsigned cache_flags);
H5_DLL herr_t         H5EA__sblock_delete(H5EA_hdr_t *hdr, H5EA_iblock_t *parent, haddr_t sblk_addr,
                                          unsigned sblk_idx);
H5_DLL herr_t         H5EA__sblock_dest(H5EA_sblock_t *sblock);

H5_DLL H5EA_dblock_t *H5EA__dblock_alloc(H5EA_hdr_t *hdr, void *parent, size_t nelmts);
H5_DLL haddr_t  H5EA__dblock_create(H5EA_hdr_t *hdr, void *parent, bool *stats_changed, hsize_t dblk_off,
                                    size_t nelmts);
H5_DLL unsigned H5EA__dblock_sblk_idx(const H5EA_hdr_t *hdr, hsize_t idx);
H5_DLL H5EA_dblock_t *H5EA__dblock_protect(H5EA_hdr_t *hdr, void *parent, haddr_t dblk_addr,
                                           size_t dblk_nelmts, unsigned flags);
H5_DLL herr_t         H5EA__dblock_unprotect(H5EA_dblock_t *dblock, unsigned cache_flags);
H5_DLL herr_t H5EA__dblock_delete(H5EA_hdr_t *hdr, void *parent, haddr_t dblk_addr, size_t dblk_nelmts);
H5_DLL herr_t H5EA__dblock_dest(H5EA_dblock_t *dblock);

H5_DLL H5EA_dblk_page_t *H5EA__dblk_page_alloc(H5EA_hdr_t *hdr, H5EA_sblock_t *parent);
H5_DLL herr_t            H5EA__dblk_page_create(H5EA_hdr_t *hdr, H5EA_sblock_t *parent, haddr_t addr);
H5_DLL H5EA_dblk_page_t *H5EA__dblk_page_protect(H5EA_hdr_t *hdr, H5EA_sblock_t *parent,
                                                 haddr_t dblk_page_addr, unsigned flags);
H5_DLL herr_t            H5EA__dblk_page_unprotect(H5EA_dblk_page_t *dblk_page, unsigned cache_flags);
H5_DLL herr_t            H5EA__dblk_page_dest(H5EA_dblk_page_t *dblk_page);

H5_DLL herr_t H5EA__hdr_debug(H5F_t *f, haddr_t addr, FILE *stream, int indent, int fwidth,
                              const H5EA_class_t *cls, haddr_t obj_addr);
H5_DLL herr_t H5EA__iblock_debug(H5F_t *f, haddr_t addr, FILE *stream, int indent, int fwidth,
                                 const H5EA_class_t *cls, haddr_t hdr_addr, haddr_t obj_addr);
H5_DLL herr_t H5EA__sblock_debug(H5F_t *f, haddr_t addr, FILE *stream, int indent, int fwidth,
                                 const H5EA_class_t *cls, haddr_t hdr_addr, unsigned sblk_idx,
                                 haddr_t obj_addr);
H5_DLL herr_t H5EA__dblock_debug(H5F_t *f, haddr_t addr, FILE *stream, int indent, int fwidth,
                                 const H5EA_class_t *cls, haddr_t hdr_addr, size_t dblk_nelmts,
                                 haddr_t obj_addr);

#ifdef H5EA_TESTING
H5_DLL herr_t H5EA__get_cparam_test(const H5EA_t *ea, H5EA_create_t *cparam);
H5_DLL int    H5EA__cmp_cparam_test(const H5EA_create_t *cparam1, const H5EA_create_t *cparam2);
#endif 

#endif 
