Line | Count | Source |
1 | | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | | * Copyright by The HDF Group. * |
3 | | * All rights reserved. * |
4 | | * * |
5 | | * This file is part of HDF5. The full HDF5 copyright notice, including * |
6 | | * terms governing use, modification, and redistribution, is contained in * |
7 | | * the LICENSE file, which can be found at the root of the source code * |
8 | | * distribution tree, or in https://www.hdfgroup.org/licenses. * |
9 | | * If you do not have access to either file, you may request a copy from * |
10 | | * help@hdfgroup.org. * |
11 | | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
12 | | |
13 | | /*------------------------------------------------------------------------- |
14 | | * |
15 | | * Created: H5HLdblk.c |
16 | | * |
17 | | * Purpose: Data block routines for local heaps. |
18 | | * |
19 | | *------------------------------------------------------------------------- |
20 | | */ |
21 | | |
22 | | /****************/ |
23 | | /* Module Setup */ |
24 | | /****************/ |
25 | | |
26 | | #include "H5HLmodule.h" /* This source code file is part of the H5HL module */ |
27 | | |
28 | | /***********/ |
29 | | /* Headers */ |
30 | | /***********/ |
31 | | #include "H5private.h" /* Generic Functions */ |
32 | | #include "H5Eprivate.h" /* Error handling */ |
33 | | #include "H5FLprivate.h" /* Free lists */ |
34 | | #include "H5HLpkg.h" /* Local Heaps */ |
35 | | #include "H5MFprivate.h" /* File memory management */ |
36 | | |
37 | | /****************/ |
38 | | /* Local Macros */ |
39 | | /****************/ |
40 | | |
41 | | /******************/ |
42 | | /* Local Typedefs */ |
43 | | /******************/ |
44 | | |
45 | | /********************/ |
46 | | /* Package Typedefs */ |
47 | | /********************/ |
48 | | |
49 | | /********************/ |
50 | | /* Local Prototypes */ |
51 | | /********************/ |
52 | | |
53 | | /*********************/ |
54 | | /* Package Variables */ |
55 | | /*********************/ |
56 | | |
57 | | /*****************************/ |
58 | | /* Library Private Variables */ |
59 | | /*****************************/ |
60 | | |
61 | | /*******************/ |
62 | | /* Local Variables */ |
63 | | /*******************/ |
64 | | |
65 | | /* Declare a free list to manage the H5HL_dblk_t struct */ |
66 | | H5FL_DEFINE_STATIC(H5HL_dblk_t); |
67 | | |
68 | | /*------------------------------------------------------------------------- |
69 | | * Function: H5HL__dblk_new |
70 | | * |
71 | | * Purpose: Create a new local heap data block object |
72 | | * |
73 | | * Return: Success: non-NULL pointer to new local heap data block |
74 | | * Failure: NULL |
75 | | * |
76 | | *------------------------------------------------------------------------- |
77 | | */ |
78 | | H5HL_dblk_t * |
79 | | H5HL__dblk_new(H5HL_t *heap) |
80 | 0 | { |
81 | 0 | H5HL_dblk_t *dblk = NULL; /* New local heap data block */ |
82 | 0 | H5HL_dblk_t *ret_value = NULL; |
83 | |
|
84 | 0 | FUNC_ENTER_PACKAGE |
85 | | |
86 | | /* check arguments */ |
87 | 0 | assert(heap); |
88 | | |
89 | | /* Allocate new local heap data block */ |
90 | 0 | if (NULL == (dblk = H5FL_CALLOC(H5HL_dblk_t))) |
91 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed for local heap data block"); |
92 | | |
93 | | /* Increment ref. count on heap data structure */ |
94 | 0 | if (FAIL == H5HL__inc_rc(heap)) |
95 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment heap ref. count"); |
96 | | |
97 | | /* Link the heap & the data block */ |
98 | 0 | dblk->heap = heap; |
99 | 0 | heap->dblk = dblk; |
100 | | |
101 | | /* Set the return value */ |
102 | 0 | ret_value = dblk; |
103 | |
|
104 | 0 | done: |
105 | | /* Ensure that the data block memory is deallocated on errors */ |
106 | 0 | if (!ret_value && dblk != NULL) |
107 | | /* H5FL_FREE always returns NULL so we can't check for errors */ |
108 | 0 | dblk = H5FL_FREE(H5HL_dblk_t, dblk); |
109 | |
|
110 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
111 | 0 | } /* end H5HL__dblk_new() */ |
112 | | |
113 | | /*------------------------------------------------------------------------- |
114 | | * Function: H5HL__dblk_dest |
115 | | * |
116 | | * Purpose: Destroy a local heap data block object |
117 | | * |
118 | | * Return: SUCCEED/FAIL |
119 | | * |
120 | | *------------------------------------------------------------------------- |
121 | | */ |
122 | | herr_t |
123 | | H5HL__dblk_dest(H5HL_dblk_t *dblk) |
124 | 0 | { |
125 | 0 | herr_t ret_value = SUCCEED; |
126 | |
|
127 | 0 | FUNC_ENTER_PACKAGE |
128 | | |
129 | | /* check arguments */ |
130 | 0 | assert(dblk); |
131 | | |
132 | | /* Check if data block was initialized */ |
133 | 0 | if (dblk->heap) { |
134 | | /* Unlink data block from heap */ |
135 | 0 | dblk->heap->dblk = NULL; |
136 | | |
137 | | /* Decrement ref. count on heap data structure */ |
138 | 0 | if (FAIL == H5HL__dec_rc(dblk->heap)) |
139 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement heap ref. count"); |
140 | | |
141 | | /* Unlink heap from data block */ |
142 | 0 | dblk->heap = NULL; |
143 | 0 | } |
144 | | |
145 | 0 | done: |
146 | | /* Free local heap data block */ |
147 | | /* H5FL_FREE always returns NULL so we can't check for errors */ |
148 | 0 | dblk = H5FL_FREE(H5HL_dblk_t, dblk); |
149 | |
|
150 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
151 | 0 | } /* end H5HL__dblk_dest() */ |
152 | | |
153 | | /*------------------------------------------------------------------------- |
154 | | * Function: H5HL__dblk_realloc |
155 | | * |
156 | | * Purpose: Reallocate data block for heap |
157 | | * |
158 | | * Return: SUCCEED/FAIL |
159 | | * |
160 | | *------------------------------------------------------------------------- |
161 | | */ |
162 | | herr_t |
163 | | H5HL__dblk_realloc(H5F_t *f, H5HL_t *heap, size_t new_heap_size) |
164 | 0 | { |
165 | 0 | H5HL_dblk_t *dblk; /* Local heap data block */ |
166 | 0 | haddr_t old_addr; /* Old location of heap data block */ |
167 | 0 | haddr_t new_addr; /* New location of heap data block */ |
168 | 0 | size_t old_heap_size; /* Old size of heap data block */ |
169 | 0 | herr_t ret_value = SUCCEED; |
170 | |
|
171 | 0 | FUNC_ENTER_PACKAGE |
172 | | |
173 | | /* Check arguments */ |
174 | 0 | assert(heap); |
175 | 0 | assert(new_heap_size > 0); |
176 | | |
177 | | /* Release old space on disk */ |
178 | 0 | old_addr = heap->dblk_addr; |
179 | 0 | old_heap_size = heap->dblk_size; |
180 | 0 | H5_CHECK_OVERFLOW(old_heap_size, size_t, hsize_t); |
181 | 0 | if (FAIL == H5MF_xfree(f, H5FD_MEM_LHEAP, old_addr, (hsize_t)old_heap_size)) |
182 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "can't free old local heap data"); |
183 | | |
184 | | /* Allocate new space on disk */ |
185 | 0 | H5_CHECK_OVERFLOW(new_heap_size, size_t, hsize_t); |
186 | 0 | if (HADDR_UNDEF == (new_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, (hsize_t)new_heap_size))) |
187 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "unable to allocate file space for local heap"); |
188 | | |
189 | | /* Update heap info*/ |
190 | 0 | heap->dblk_addr = new_addr; |
191 | 0 | heap->dblk_size = new_heap_size; |
192 | | |
193 | | /* Check if heap data block actually moved in the file */ |
194 | 0 | if (H5_addr_eq(old_addr, new_addr)) { |
195 | | /* Check if heap data block is contiguous w/prefix */ |
196 | 0 | if (heap->single_cache_obj) { |
197 | | /* Sanity check */ |
198 | 0 | assert(H5_addr_eq(heap->prfx_addr + heap->prfx_size, old_addr)); |
199 | 0 | assert(heap->prfx); |
200 | | |
201 | | /* Resize the heap prefix in the cache */ |
202 | 0 | if (FAIL == H5AC_resize_entry(heap->prfx, (size_t)(heap->prfx_size + new_heap_size))) |
203 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "unable to resize heap in cache"); |
204 | 0 | } |
205 | 0 | else { |
206 | | /* Sanity check */ |
207 | 0 | assert(H5_addr_ne(heap->prfx_addr + heap->prfx_size, old_addr)); |
208 | 0 | assert(heap->dblk); |
209 | | |
210 | | /* Resize the heap data block in the cache */ |
211 | 0 | if (H5AC_resize_entry(heap->dblk, (size_t)new_heap_size) < 0) |
212 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "unable to resize heap (data block) in cache"); |
213 | 0 | } |
214 | 0 | } |
215 | 0 | else { |
216 | | /* Check if heap data block was contiguous w/prefix previously */ |
217 | 0 | if (heap->single_cache_obj) { |
218 | | /* Create new heap data block */ |
219 | 0 | if (NULL == (dblk = H5HL__dblk_new(heap))) |
220 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "unable to allocate local heap data block"); |
221 | | |
222 | | /* Resize current heap prefix */ |
223 | 0 | heap->prfx_size = H5HL_SIZEOF_HDR(f); |
224 | 0 | if (FAIL == H5AC_resize_entry(heap->prfx, (size_t)heap->prfx_size)) |
225 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "unable to resize heap prefix in cache"); |
226 | | |
227 | | /* Insert data block into cache (pinned) */ |
228 | 0 | if (FAIL == H5AC_insert_entry(f, H5AC_LHEAP_DBLK, new_addr, dblk, H5AC__PIN_ENTRY_FLAG)) |
229 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to cache local heap data block"); |
230 | | |
231 | 0 | dblk = NULL; |
232 | | |
233 | | /* Reset 'single cache object' flag */ |
234 | 0 | heap->single_cache_obj = false; |
235 | 0 | } |
236 | 0 | else { |
237 | | /* Resize the heap data block in the cache */ |
238 | | /* (ignore [unlikely] case where heap data block ends up |
239 | | * contiguous w/heap prefix again. |
240 | | */ |
241 | 0 | if (FAIL == H5AC_resize_entry(heap->dblk, (size_t)new_heap_size)) |
242 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "unable to resize heap data block in cache"); |
243 | | |
244 | | /* Relocate the heap data block in the cache */ |
245 | 0 | if (FAIL == H5AC_move_entry(f, H5AC_LHEAP_DBLK, old_addr, new_addr)) |
246 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move heap data block in cache"); |
247 | 0 | } |
248 | 0 | } |
249 | | |
250 | 0 | done: |
251 | | /* Restore old heap address & size on errors */ |
252 | 0 | if (FAIL == ret_value) { |
253 | 0 | heap->dblk_addr = old_addr; |
254 | 0 | heap->dblk_size = old_heap_size; |
255 | 0 | } |
256 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
257 | 0 | } /* end H5HL__dblk_realloc() */ |