1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Copyright by The HDF Group. *
3 * Copyright by the Board of Trustees of the University of Illinois. *
4 * All rights reserved. *
5 * *
6 * This file is part of HDF. The full HDF copyright notice, including *
7 * terms governing use, modification, and redistribution, is contained in *
8 * the COPYING file, which can be found at the root of the source code *
9 * distribution tree, or in https://support.hdfgroup.org/ftp/HDF/releases/. *
10 * If you do not have access to either file, you may request a copy from *
11 * help@hdfgroup.org. *
12 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13
14 /* $Id$ */
15
16 /*LINTLIBRARY */
17 /* ------------------------------ hblocks.c -------------------------------
18 routines to implement linked-block elements
19
20 Linked element in HDF files created in two ways
21 -- created from the start or
22 -- converted from a normal data element
23
24 A linked-block element is a special element.
25
26 Special elements are
27 flagged with a set high-bit in their tag. Thus, a tag t has
28 BASETAG == t & 0x7f and is a special tag if t & 0x80 != 0x00
29
30 The first 16 bits of the meta-element that this tag/ref points to
31 tells us what type of special element this is. If these 16 bits is
32 SPECIAL_LINKED, then it contains information about the linked blocks.
33 After this 16 bits, 32 bit which is the length of each block, after
34 which is the information header:
35
36 ----------------------------------------------------------------------
37 | # blocks in | tag/ref of | tag/ref of blocks list ....... |
38 | this header | next header| |
39 ----------------------------------------------------------------------
40
41 File Description of Linked Block Element
42 ****************************************
43 DD for Linked Block pointing to Linked Block Description Record
44 ==============================================================
45 <- 2 bytes -> <- 2 bytes -> <- 4 bytes -> <- 4bytes ->
46 --------------------------------------------------------
47 |extended tag | reference # | Offset | Length |
48 --------------------------------------------------------
49 \______________/
50 __________________________________________|
51 V
52 LINKED BLOCK DESCRIPTION RECORD(LBDR - 16 bytes)
53 ===============================================
54 <- 2 bytes -> <- 4 bytes -> <- 4 bytes -> <- 4 bytes -> <- 2 bytes ->
55 ---------------------------------------------- ------------------------
56 |ext_tag_desc | elem_tot_len | blk_length | num_blk | link_ref |
57 ---------------------------------------------- ------------------------
58
59
60 ext_tag_desc - SPECIAL_LINKED(16 bit constant), identifies this as
61 a linked block description record
62 elem_tot_len - Length of the entire element(32 bit field)
63 blk_length - Length of successive data blocks(32 bit field) after first block,
64 first block is calculated.
65 num_blk - Number of blocks per block table(32 bit field)
66 link_ref - Reference number of the first block table(16 bit field)
67
68 Linked Block Table(12 + 2 + 2 + 2 + 2 + ... bytes)
69 ===================================================
70 <- 2 bytes -> <- 2 bytes -> <- 4 bytes -> <- 4bytes ->
71 --------------------------------------------------------
72 |link_blk_tag | link_ref | Offset | Length |
73 --------------------------------------------------------
74 \______________/
75 __________________________________________|
76 V
77 <- 2 bytes -> <- 2 bytes -> <- 2 bytes -> <- 2 bytes -> <-...
78 -----------------------------------------------------------...
79 | next_ref | block_ref_1 | block_ref_2 | block_ref_3 | ...
80 -----------------------------------------------------------...
81
82 link_blk_tag - DFTAG_LINKED(16 bit)
83 link_ref - Reference number for this table(16 bit)
84 next_ref - Reference number for next block table(16 bit)
85 Zero(0) signifies no more block tables for this element.
86 blk_ref_x - Reference number for data block X (16 bit).
87 e.g. for data block 1
88 <- 2 bytes -> <- 2 bytes -> <- 4 bytes -> <- 4bytes ->
89 --------------------------------------------------------
90 | DFTAG_LINKED | block_ref_1 | Offset | Length |
91 --------------------------------------------------------
92 \______________/
93 __________________________________________|
94 V
95 -----------------------
96 | Data_block |
97 -----------------------
98 Note: The "Length" here is specified by either
99 "elem_first_len" or "blk_length".
100
101 For now, HLcreate() has the best description of what the on-disk
102 representation of a linked block element looks like.
103
104 EXPORTED ROUTINES
105
106 HLcreate -- create a linked block element
107 HLconvert -- convert an AID into a linked block element
108 HLgetdatainfo -- get data information of linked blocks
109 HDinqblockinfo -- return info about linked blocks
110 HLPstread -- open an access record for reading
111 HLPstwrite -- open an access record for writing
112 HLPseek -- set the seek posn
113 HLPread -- read some data out of a linked block element
114 HLPwrite -- write out some data to a linked block
115 HLPinquire -- Hinquire for linked blocks
116 HLPendacess -- close a linked block AID
117 HLPinfo -- return info about a linked block element
118 LOCAL ROUTINES
119 HLIstaccess -- set up AID to access a linked block elem
120 HLIgetlink -- get link information
121 HLInewlink -- write out some data to a linked block
122 */
123
124 #include "hdf.h"
125 #include "hfile.h"
126
127 /* block_t - record of a linked block. contains the tag and ref of the
128 data elt that forms the linked block */
129 typedef struct block_t
130 {
131 uint16 ref; /* ref of the linked block */
132 }
133 block_t;
134
135 /* link_t - a linked list block table.
136 Very similar to the dd block structure */
137 typedef struct link_t
138 {
139 uint16 nextref; /* ref of the next block table */
140 struct link_t *next; /* ptr to the next block table */
141 struct block_t *block_list;/* ptr to the block list for this table */
142 }
143 link_t;
144
145 /* information on this special linked block data elt */
146 typedef struct linkinfo_t
147 {
148 int attached; /* how many access records refer to this elt */
149 int32 length; /* the actual length of the data elt */
150 int32 first_length; /* length of first block */
151 int32 block_length; /* the length of the remaining blocks */
152 int32 number_blocks;/* total number of blocks in each link/block table */
153 uint16 link_ref; /* ref of the first block table structure */
154 link_t *link; /* pointer to the first block table */
155 link_t *last_link; /* pointer to the last block table */
156 }
157 linkinfo_t;
158
159 /* private functions */
160 PRIVATE int32 HLIstaccess(accrec_t *access_rec,
161 int16 acc_mode);
162
163 PRIVATE link_t *HLInewlink(int32 file_id,
164 int32 number_blocks,
165 uint16 link_ref,
166 uint16 first_block_ref);
167
168 PRIVATE link_t *HLIgetlink(int32 file_id,
169 uint16 ref,
170 int32 number_blocks);
171
172 /* the accessing function table for linked blocks */
173 funclist_t linked_funcs =
174 {
175 HLPstread,
176 HLPstwrite,
177 HLPseek,
178 HLPinquire,
179 HLPread,
180 HLPwrite,
181 HLPendaccess,
182 HLPinfo,
183 NULL /* no routine registered */
184 };
185
186 /* ------------------------------------------------------------------------
187 NAME
188 HLcreate -- create a linked block element
189 USAGE
190 int32 HLcreate(fid, tag, ref, blocklen, numblocks)
191 int32 fid; IN: file to put linked block element in
192 uint16 tag; IN: tag of element
193 uint16 ref; IN: ref of element
194 int32 blocklen; IN: length of standard block
195 int32 numblocks; IN: number of blocks per block list
196 RETURNS
197 The AID of newly created linked block element, FAIL on error.
198 DESCRIPTION
199 This routine takes an HDF element and promotes it into a linked
200 block element. Basically, the element becomes a linked list
201 allowing easy appending. If the element already exists, it
202 is promoted to being a linked block element, otherwise a new
203 element is created.
204
205 All of the pieces of the linked list are the same size (blocklen)
206 except for the first one which stays the size of the element
207 at the time HLcreate was called.
208
209 numblocks gives the number of linked list objects in each
210 block header.
211
212 The ideal setting for numblocks and blocklen are very data
213 and application depedent.
214
215 --------------------------------------------------------------------------- */
216 int32
HLcreate(int32 file_id,uint16 tag,uint16 ref,int32 block_length,int32 number_blocks)217 HLcreate(int32 file_id,
218 uint16 tag,
219 uint16 ref,
220 int32 block_length,
221 int32 number_blocks)
222 {
223 CONSTR(FUNC, "HLcreate"); /* for HERROR */
224 filerec_t *file_rec; /* file record */
225 accrec_t *access_rec=NULL;/* access record */
226 int32 dd_aid; /* AID for writing the special info */
227 linkinfo_t *info = NULL; /* information for the linked blocks elt */
228 uint16 link_ref; /* the ref of the link structure
229 (block table) */
230 atom_t data_id; /* dd ID of existing regular element */
231 uint16 new_data_tag, new_data_ref=0; /* Tag/ref of the new data in the file */
232 int32 data_len; /* length of the data we are checking */
233 int32 data_off; /* offset of the data we are checking */
234 uint16 special_tag; /* special version of this tag */
235 uint8 local_ptbuf[16];
236 int32 ret_value = SUCCEED;
237
238 /* clear error stack and validate file record id */
239 HEclear();
240 file_rec = HAatom_object(file_id);
241
242 /* check args and create special tag */
243 if (BADFREC(file_rec) || block_length < 0 || number_blocks < 0
244 || SPECIALTAG(tag)
245 || (special_tag = MKSPECIALTAG(tag)) == DFTAG_NULL)
246 HGOTO_ERROR(DFE_ARGS, FAIL);
247
248 /* make sure write access to file */
249 if (!(file_rec->access & DFACC_WRITE))
250 HGOTO_ERROR(DFE_DENIED, FAIL);
251
252 /* get empty access record */
253 access_rec = HIget_access_rec();
254 if (access_rec == NULL)
255 HGOTO_ERROR(DFE_TOOMANY, FAIL);
256
257 /* search for identical dd */
258 if ((data_id = HTPselect(file_rec,tag,ref))!=FAIL)
259 {
260 /* Check if the element is already special */
261 if (HTPis_special(data_id)==TRUE)
262 {
263 HTPendaccess(data_id);
264 HGOTO_ERROR(DFE_CANTMOD, FAIL);
265 } /* end if */
266
267 /* If the data already was in the file,
268 * convert it into the first linked block
269 * get the info for the dataset */
270 if(HTPinquire(data_id,NULL,NULL,&data_off,&data_len)==FAIL)
271 {
272 HTPendaccess(data_id);
273 HGOTO_ERROR(DFE_INTERNAL, FAIL);
274 } /* end if */
275
276 if(data_off == INVALID_OFFSET || data_len==INVALID_LENGTH)
277 { /* data object which has been created, but has no data */
278 /* Delete the old data ID */
279 if(HTPdelete(data_id)==FAIL)
280 HGOTO_ERROR(DFE_CANTDELHASH, FAIL);
281
282 data_id=FAIL; /* reset this so the first block is a "regular" fixed length block */
283 } /* end if */
284 else
285 { /* existing data object with real data in it */
286 new_data_tag = DFTAG_LINKED;
287 new_data_ref = Htagnewref(file_id,new_data_tag);
288 /* create new linked-block table DD to point to existing data */
289 if(Hdupdd(file_id, new_data_tag, new_data_ref, tag, ref)==FAIL)
290 {
291 HTPendaccess(data_id);
292 HGOTO_ERROR(DFE_CANTUPDATE, FAIL);
293 } /* end if */
294
295 /* Delete the old data ID */
296 if(HTPdelete(data_id)==FAIL)
297 HGOTO_ERROR(DFE_CANTDELHASH, FAIL);
298
299 /* Attach to the new data ID */
300 if ((data_id = HTPselect(file_rec,new_data_tag,new_data_ref))==FAIL)
301 HGOTO_ERROR(DFE_INTERNAL, FAIL);
302 } /* end else */
303 } /* end if */
304
305 /* get ref for next linked-block? */
306 link_ref = Htagnewref(file_id,DFTAG_LINKED);
307
308 /* allocate and fill special info struct */
309 if (( info = (linkinfo_t *) HDmalloc((uint32) sizeof(linkinfo_t)))==NULL)
310 HGOTO_ERROR(DFE_NOSPACE, FAIL);
311
312 info->attached = 1;
313 info->length = (data_id!=FAIL) ? data_len : 0;
314 info->first_length = (data_id!=FAIL) ? data_len : block_length;
315 info->block_length = block_length;
316 info->number_blocks = number_blocks;
317 info->link_ref = link_ref;
318
319 /* encode special information for writing to file */
320 {
321 uint8 *p;
322 p = local_ptbuf;
323 UINT16ENCODE(p, SPECIAL_LINKED);
324 INT32ENCODE(p, info->length);
325 INT32ENCODE(p, block_length);
326 INT32ENCODE(p, number_blocks);
327 UINT16ENCODE(p, link_ref); /* link_ref */
328 }
329
330 /* write the special info structure */
331 if((dd_aid = Hstartaccess(file_id,special_tag,ref,DFACC_ALL))==FAIL)
332 HGOTO_ERROR(DFE_CANTACCESS, FAIL);
333 if (Hwrite(dd_aid, 16, local_ptbuf) == FAIL)
334 HGOTO_ERROR(DFE_WRITEERROR, FAIL);
335 if(Hendaccess(dd_aid)==FAIL)
336 HGOTO_ERROR(DFE_CANTENDACCESS, FAIL);
337
338 /* write out linked block */
339 info->link = HLInewlink(file_id, number_blocks, link_ref,
340 (uint16) ((data_id!=FAIL) ? new_data_ref : 0));
341 if (!info->link)
342 HGOTO_ERROR(DFE_INTERNAL, FAIL);
343
344 /* Detach from the data DD ID */
345 if(data_id != FAIL)
346 {
347 if(HTPendaccess(data_id)==FAIL)
348 HGOTO_ERROR(DFE_INTERNAL, FAIL);
349 }
350
351 /* update access record and file record */
352 if((access_rec->ddid=HTPselect(file_rec,special_tag,ref))==FAIL)
353 HGOTO_ERROR(DFE_INTERNAL, FAIL);
354
355 access_rec->special_func = &linked_funcs;
356 access_rec->special_info = (void *)info;
357 access_rec->special = SPECIAL_LINKED;
358 access_rec->posn = 0;
359 access_rec->access = DFACC_RDWR;
360 access_rec->file_id = file_id;
361 access_rec->appendable = FALSE; /* start data as non-appendable */
362
363 file_rec->attach++; /* increment number of elements attached to file */
364
365 /* set return value */
366 ret_value = HAregister_atom(AIDGROUP,access_rec);
367
368 done:
369 if(ret_value == FAIL)
370 { /* Error condition cleanup */
371 if (info != NULL)
372 HDfree(info);
373 if(access_rec!=NULL)
374 HIrelease_accrec_node(access_rec);
375 } /* end if */
376
377 /* Normal function cleanup */
378 return ret_value;
379 } /* HLcreate() */
380
381 /* ------------------------------------------------------------------------
382 NAME
383 HLconvert -- convert an AID into a linked block element
384 USAGE
385 intn HLconvert(aid, blocklen, numblocks)
386 int32 aid; IN: AID to convert
387 int32 blocklen; IN: length of standard block
388 int32 numblocks; IN: number of blocks per block list
389 RETURNS
390 SUCCEED / FAIL
391 DESCRIPTION
392 This routine takes an HDF element and promotes it into a linked
393 block element. Basically, the element becomes a linked list
394 allowing easy appending. If the element already exists, it
395 is promoted to being a linked block element, otherwise a new
396 element is created.
397
398 All of the pieces of the linked list are the same size (blocklen)
399 except for the first one which stays the size of the element
400 at the time HLcreate was called.
401
402 This routine is similar to HLcreate but is used to convert an
403 existing AID into a linked block element "in-place". This is
404 done for convenience and ease-of-use mostly internally to the
405 library in various places, but it is allowable for user-level
406 code to do this also.
407
408 Hopefully HLcreate will get re-written to call this routine for
409 most of it's work...
410
411 numblocks gives the number of linked list objects in each
412 block header.
413
414 The ideal setting for numblocks and blocklen are very data
415 and application depedent.
416
417 ---------------------------------------------------------------------------*/
418 intn
HLconvert(int32 aid,int32 block_length,int32 number_blocks)419 HLconvert(int32 aid,
420 int32 block_length,
421 int32 number_blocks)
422 {
423 CONSTR(FUNC, "HLconvert"); /* for HERROR */
424 filerec_t *file_rec; /* file record */
425 accrec_t *access_rec=NULL;/* access record */
426 linkinfo_t *info; /* information for the linked blocks elt */
427 uint16 link_ref; /* the ref of the link structure
428 (block table) */
429 int32 dd_aid; /* AID for writing the special info */
430 uint16 new_data_tag=DFTAG_NULL, new_data_ref=0; /* Tag/ref of the new data in the file */
431 uint16 data_tag, data_ref; /* Tag/ref of the data in the file */
432 int32 data_len; /* length of the data we are checking */
433 int32 data_off; /* offset of the data we are checking */
434 uint16 special_tag; /* special version of this tag */
435 int32 file_id; /* file ID for the access record */
436 uint8 local_ptbuf[16];
437 int32 old_posn; /* position in the access element */
438 intn ret_value = SUCCEED;
439
440 /* clear error stack */
441 HEclear();
442
443 /* start checking the func. args */
444 if (HAatom_group(aid)!=AIDGROUP || block_length < 0 || number_blocks < 0)
445 HGOTO_ERROR(DFE_ARGS, FAIL);
446
447 /* get the access_rec pointer */
448 if ((access_rec = HAatom_object(aid)) == NULL)
449 HGOTO_ERROR(DFE_ARGS, FAIL);
450
451 file_id = access_rec->file_id;
452 file_rec = HAatom_object(file_id);
453 if (BADFREC(file_rec))
454 HGOTO_ERROR(DFE_ARGS, FAIL);
455
456 if (!(file_rec->access & DFACC_WRITE))
457 HGOTO_ERROR(DFE_DENIED, FAIL);
458
459 /* verify that the object is not already special. Can not convert
460 if already special. */
461 if (HTPis_special(access_rec->ddid))
462 HGOTO_ERROR(DFE_CANTMOD, FAIL);
463
464 /* Save previous position in data element so that we can come back to it */
465 old_posn=access_rec->posn;
466
467 /* get the info for the dataset */
468 if(HTPinquire(access_rec->ddid,&data_tag,&data_ref,&data_off,&data_len)==FAIL)
469 HGOTO_ERROR(DFE_INTERNAL, FAIL);
470
471 /* make data tag special i.e. will be linked-block element */
472 if ((special_tag = MKSPECIALTAG(data_tag)) == DFTAG_NULL)
473 HGOTO_ERROR(DFE_BADDDLIST, FAIL);
474
475 /* is data defined but does not exist in the file? */
476 if(data_off==INVALID_OFFSET && data_len==INVALID_LENGTH)
477 { /* catch the case where the data doesn't exist yet */
478
479 /* set length to zero */
480 if(Hsetlength(aid,0)==FAIL)
481 HGOTO_ERROR(DFE_INTERNAL, FAIL);
482
483 /* get back new offset and length */
484 if(HTPinquire(access_rec->ddid,&data_tag,&data_ref,&data_off,&data_len)==FAIL)
485 HGOTO_ERROR(DFE_INTERNAL, FAIL);
486 } /* end if */
487
488 /* set up new tag/ref for linked block element */
489 new_data_tag = DFTAG_LINKED;
490 new_data_ref = Htagnewref(file_id,new_data_tag);
491
492 /* make new tag/ref point to existing data element */
493 if(Hdupdd(file_id, new_data_tag, new_data_ref, data_tag, data_ref)==FAIL)
494 HGOTO_ERROR(DFE_CANTUPDATE, FAIL);
495
496 /* Delete the old data ID */
497 if(HTPdelete(access_rec->ddid)==FAIL)
498 HGOTO_ERROR(DFE_CANTDELHASH, FAIL);
499
500 /* Attach to the new data ID */
501 if ((access_rec->ddid=HTPcreate(file_rec,special_tag,data_ref))==FAIL)
502 HGOTO_ERROR(DFE_INTERNAL, FAIL);
503
504 /* get link ref for linked-block ? */
505 link_ref = Htagnewref(file_id,DFTAG_LINKED);
506
507 /* allocates special info struct for linked blocks */
508 access_rec->special_info = HDmalloc((uint32) sizeof(linkinfo_t));
509 if (!access_rec->special_info)
510 HGOTO_ERROR(DFE_NOSPACE, FAIL);
511
512 /* fill in special info struct */
513 info = (linkinfo_t *) access_rec->special_info;
514 info->attached = 1;
515 info->length = data_len;
516 info->first_length = data_len;
517 info->block_length = block_length;
518 info->number_blocks = number_blocks;
519 info->link_ref = link_ref;
520
521 /* Get ready to fill and write the special info structure */
522
523 /* start write access on special tag/ref */
524 if((dd_aid=Hstartaccess(file_id,special_tag,data_ref,DFACC_ALL))==FAIL)
525 HGOTO_ERROR(DFE_CANTACCESS, FAIL);
526
527 /* encode special information to write out */
528 {
529 uint8 *p;
530
531 p = local_ptbuf;
532 UINT16ENCODE(p, SPECIAL_LINKED);
533 INT32ENCODE(p, info->length);
534 INT32ENCODE(p, block_length);
535 INT32ENCODE(p, number_blocks);
536 UINT16ENCODE(p, link_ref); /* link_ref */
537 }
538
539 /* write out special information */
540 if (Hwrite(dd_aid, 16, local_ptbuf) == FAIL)
541 HGOTO_ERROR(DFE_WRITEERROR, FAIL);
542 if(Hendaccess(dd_aid)==FAIL)
543 HGOTO_ERROR(DFE_CANTENDACCESS, FAIL);
544
545 /* write out linked block */
546 if ((info->link = HLInewlink(file_id, number_blocks, link_ref, (uint16)new_data_ref)) ==NULL)
547 HGOTO_ERROR(DFE_CANTLINK, FAIL);
548
549 /* update access record and file record */
550 access_rec->special_func = &linked_funcs;
551 access_rec->special = SPECIAL_LINKED;
552 access_rec->appendable = FALSE; /* start data as non-appendable */
553
554 /* check whether we should seek out to the proper position */
555 if(old_posn>0)
556 {
557 if(Hseek(aid,old_posn,DF_START)==FAIL)
558 HGOTO_ERROR(DFE_BADSEEK, FAIL);
559 } /* end if */
560
561 done:
562 if(ret_value == FAIL)
563 { /* Error condition cleanup */
564 if(access_rec->special_info != NULL)
565 HDfree(access_rec->special_info);
566 if(access_rec!=NULL)
567 HIrelease_accrec_node(access_rec);
568 } /* end if */
569
570 /* Normal function cleanup */
571 return ret_value;
572 } /* end HLconvert() */
573
574 /* ---------------------------- HDinqblockinfo ---------------------------- */
575 /*
576 NAME
577 HDinqblockinfo -- return info about linked blocks
578 USAGE
579 int32 HDinqblockinfo(aid, length, flength, blen, nblocks)
580 int32 aid; IN: aid of element
581 int32 * length; OUT: total element length
582 int32 * flength; OUT: length of first element
583 int32 * blen; OUT: length of block elements
584 int32 * nblocks; OUT: number of blocks per block header
585 RETURNS
586 SUCCEED / FAIL
587 DESCRIPTION
588 Given an aid, return low level special info for linked-block
589 element in space provided. This function works like HDinquire()
590 but provides more low level info than HLPinquire. NULL can
591 be passed for any non-interesting entries.
592
593 hdfpack is the only application that I know of which uses
594 this function.
595
596 ---------------------------------------------------------------------------*/
597 int
HDinqblockinfo(int32 aid,int32 * length,int32 * first_length,int32 * block_length,int32 * number_blocks)598 HDinqblockinfo(int32 aid,
599 int32 *length,
600 int32 *first_length,
601 int32 *block_length,
602 int32 *number_blocks)
603 {
604 accrec_t *arec;
605 int ret_value = SUCCEED;
606 CONSTR(FUNC, "HDinqblockinfo");
607
608 HEclear();
609 if ((arec = HAatom_object(aid)) == (accrec_t *) NULL)
610 HGOTO_ERROR(DFE_BADAID, FAIL);
611
612 if (arec->special != SPECIAL_LINKED)
613 HGOTO_ERROR(DFE_ARGS, FAIL);
614
615 if (length)
616 *length = ((linkinfo_t *) (arec->special_info))->length;
617 if (first_length)
618 *first_length = ((linkinfo_t *) (arec->special_info))->first_length;
619 if (block_length)
620 *block_length = ((linkinfo_t *) (arec->special_info))->block_length;
621 if (number_blocks)
622 *number_blocks = ((linkinfo_t *) (arec->special_info))->number_blocks;
623
624 done:
625 if(ret_value == FAIL)
626 { /* Error condition cleanup */
627
628 } /* end if */
629
630 /* Normal function cleanup */
631
632 return ret_value;
633 } /* HDinqblockinfo */
634
635 /* ----------------------------- HLIstaccess ------------------------------ */
636 /*
637 NAME
638 HLIstaccess -- set up AID to access a linked block elem
639 USAGE
640 int32 HLIstaccess(access_rec, acc_mode)
641 access_t * access_rec; IN: access record to fill in
642 int16 acc_mode; IN: access mode
643 RETURNS
644 The AID of the access record on success FAIL on error.
645 DESCRIPTION
646 Calls to HLIstread and HLIstwrite resolve to this function.
647 Given an active AID fill in all of the special information.
648 If this information has already been read in for a different
649 element use that else we must go out to the HDF file and
650 pull in the information ourselves
651
652 ----------------------------------------------------------------------------*/
653 PRIVATE int32
HLIstaccess(accrec_t * access_rec,int16 acc_mode)654 HLIstaccess(accrec_t *access_rec,
655 int16 acc_mode)
656 {
657 CONSTR(FUNC, "HLIstaccess"); /* for HERROR */
658 filerec_t *file_rec; /* file record */
659 linkinfo_t *info = NULL; /* information about data elt */
660 int32 dd_aid; /* AID for writing the special info */
661 uint16 data_tag, data_ref; /* Tag/ref of the data in the file */
662 uint8 local_ptbuf[14];
663 int32 ret_value = SUCCEED;
664
665 /* validate file record id */
666 file_rec = HAatom_object(access_rec->file_id);
667 if (BADFREC(file_rec) || !(file_rec->access & acc_mode))
668 HGOTO_ERROR(DFE_ARGS, FAIL);
669
670 /* set up some data in access record */
671 access_rec->special = SPECIAL_LINKED;
672 access_rec->posn = 0;
673 access_rec->access = (uint32)(acc_mode|DFACC_READ);
674
675 /*
676 * Lets free old special info first,if one exists,
677 * before copying a new one
678 */
679 if (access_rec->special_info != NULL)
680 { /* special information record */
681 linkinfo_t *t_info = (linkinfo_t *) access_rec->special_info;
682
683 if (--(t_info->attached) == 0)
684 {
685 link_t *t_link; /* current link to free */
686 link_t *next; /* next link to free */
687
688 /* free the linked list of links/block tables */
689 if(t_info->link!=NULL)
690 {
691 for (t_link = t_info->link; t_link; t_link = next)
692 {
693 next = t_link->next;
694 if(t_link->block_list!=NULL)
695 HDfree(t_link->block_list);
696 HDfree(t_link);
697 }
698 } /* end if */
699 HDfree(t_info);
700 access_rec->special_info = NULL;
701 }
702 }
703
704 /* get the info for the dataset */
705 if(HTPinquire(access_rec->ddid,&data_tag,&data_ref,NULL,NULL)==FAIL)
706 HGOTO_ERROR(DFE_INTERNAL, FAIL);
707
708 /* if the special information are already in some other acc elt,
709 * point to it */
710 access_rec->special_info = HIgetspinfo(access_rec);
711 if (access_rec->special_info)
712 {
713 ((linkinfo_t *) access_rec->special_info)->attached++;
714 file_rec->attach++;
715 ret_value = HAregister_atom(AIDGROUP,access_rec);
716 goto done; /* we are done */
717 }
718
719 /* read the special info structure from the file */
720 if((dd_aid = Hstartaccess(access_rec->file_id,data_tag,data_ref,DFACC_READ))==FAIL)
721 HGOTO_ERROR(DFE_CANTACCESS, FAIL);
722 if (Hseek(dd_aid, 2, DF_START) == FAIL)
723 HGOTO_ERROR(DFE_SEEKERROR, FAIL);
724 if (Hread(dd_aid, 14, local_ptbuf) == FAIL)
725 HGOTO_ERROR(DFE_READERROR, FAIL);
726 if(Hendaccess(dd_aid)==FAIL)
727 HGOTO_ERROR(DFE_CANTENDACCESS, FAIL);
728
729 /* allocate space for special information */
730 access_rec->special_info = HDmalloc((uint32) sizeof(linkinfo_t));
731 info = (linkinfo_t *) access_rec->special_info;
732 if (!info)
733 HGOTO_ERROR(DFE_NOSPACE, FAIL);
734
735 /* decode special information retrieved from file into info struct */
736 {
737 uint8 *p = local_ptbuf;
738 INT32DECODE(p, info->length);
739 INT32DECODE(p, info->block_length);
740 INT32DECODE(p, info->number_blocks);
741 UINT16DECODE(p, info->link_ref);
742 }
743
744 /* get the block length and number of blocks */
745 access_rec->block_size = info->block_length;
746 access_rec->num_blocks = info->number_blocks;
747
748 /* set up the block tables of the information */
749 info->link = HLIgetlink(access_rec->file_id,
750 info->link_ref, info->number_blocks);
751 if (!info->link)
752 HGOTO_DONE(FAIL);
753
754 /* find and set the length of the first linked-block */
755 if (info->link->block_list[0].ref)
756 {
757 info->first_length = Hlength(access_rec->file_id, DFTAG_LINKED,
758 info->link->block_list[0].ref);
759 if (info->first_length == FAIL)
760 {
761 HDfree(info->link);
762 HGOTO_ERROR(DFE_INTERNAL, FAIL);
763 }
764 }
765 else
766 info->first_length = info->block_length;
767
768 /* process through all the linked-blocks in the file for this element */
769 info->last_link = info->link;
770 while (info->last_link->nextref != 0)
771 {
772 info->last_link->next = HLIgetlink(access_rec->file_id,
773 info->last_link->nextref, info->number_blocks);
774 if (!info->last_link->next)
775 {
776 link_t *l, *next;
777
778 for (l = info->link; l; l = next)
779 {
780 next = l->next;
781 if (l->block_list)
782 HDfree(l->block_list);
783 HDfree(l);
784 }
785 HGOTO_ERROR(DFE_INTERNAL, FAIL);
786 }
787 info->last_link = info->last_link->next;
788 }
789
790 /* update data */
791 info->attached = 1;
792
793 file_rec->attach++; /* increment number of elements attached to file */
794
795 ret_value = HAregister_atom(AIDGROUP,access_rec);
796
797 done:
798 if(ret_value == FAIL)
799 { /* Error condition cleanup */
800 if(access_rec->special_info != NULL)
801 HDfree(access_rec->special_info);
802 } /* end if */
803
804 /* Normal function cleanup */
805
806 return ret_value;
807 } /* HLIstaccess */
808
809 /* ----------------------------- HLgetdatainfo --------------------------- */
810 /*
811 NAME
812 HLgetdatainfo -- get data information from linked blocks
813 USAGE
814 int32 HLgetdatainfo(file_id, link_ref, num_blocks, offsetarray, lengtharray)
815 int32 file_id; IN: the file
816 uint8 *buf; IN: special header info read from the file by caller
817 uintn start_block, IN: data block to start at, 0 base
818 uintn info_count, IN: size of offset/length lists
819 int32 *offsetarray; OUT: offsets of data blocks
820 int32 *lengtharray; OUT: lengths of data blocks
821 RETURNS
822 The number of actual data blocks, if successful, FAIL, otherwise
823 DESCRIPTION
824 HLgetdatainfo uses HLIgetlink to get each block table in the element.
825 We're looking for actual data blocks which have a positive reference number.
826 Blocks with ref# as 0 will signal the end of the actual data blocks.
827 HLgetdatainfo goes through the block table to record offset and length of
828 the actual data blocks.
829 Aug 08, 2010 -BMR
830 TODO
831 - No effect from start_block yet; since it's not used in the HDF Mapping
832 project, and we're running out of time, I'm leaving it out.
833 Feb 18, 2011 -BMR
834 ---------------------------------------------------------------------------*/
835 intn
HLgetdatainfo(int32 file_id,uint8 * buf,uintn start_block,uintn info_count,int32 * offsetarray,int32 * lengtharray)836 HLgetdatainfo(int32 file_id,
837 uint8 *buf, /* IN: special header info */
838 uintn start_block, /* IN: data block to start at, 0 base */
839 uintn info_count, /* IN: size of offset/length lists */
840 int32 *offsetarray, /* OUT: array to hold offsets */
841 int32 *lengtharray) /* OUT: array to hold lengths */
842 {
843 CONSTR(FUNC, "HLgetdatainfo"); /* for HERROR */
844 link_t *link_info=NULL; /* link information, to get block ref#s*/
845 intn num_data_blocks; /* number of blocks that actually have data */
846 uint16 link_ref; /* ref# pointing to a block table */
847 uint8 *p=NULL; /* pointer to special info buffer */
848 int32 num_blocks, /* number of blocks in each table */
849 block_length, /* length of each block */
850 total_length, /* total data length of the element */
851 accum_length; /* accummulative length of actual data in blocks */
852 int ii;
853 intn ret_value = SUCCEED;
854
855 /* Clear error stack */
856 HEclear();
857
858 /* Validate arguments */
859 if (info_count == 0 && offsetarray != NULL && lengtharray != NULL)
860 HGOTO_ERROR(DFE_ARGS, FAIL);
861
862 /* Decode special information retrieved from file */
863 p = &buf[0];
864 INT32DECODE(p, total_length);
865 INT32DECODE(p, block_length);
866 INT32DECODE(p, num_blocks); /* get number of blocks in link table */
867 UINT16DECODE(p, link_ref); /* get ref# link table */
868
869 /* Initialize number of actual data blocks and the accumulative data len */
870 num_data_blocks = 0;
871 accum_length = 0;
872
873 /* Get the block table pointed to by link_ref; the table contains ref#s of
874 the blocks */
875 link_info = HLIgetlink(file_id, link_ref, num_blocks);
876 if (!link_info) /* no data */
877 HGOTO_DONE(FAIL);
878
879 /* Go through all the linked-block tables of this element, as long as the
880 number of data blocks being collected has not reached the maximum length
881 of the non-NULL arrays provided */
882 while (link_info != NULL &&
883 (info_count == 0 || /* case of offset/length arrays being NULL */
884 num_data_blocks < info_count))
885 {
886 uint16 next_ref = link_info->nextref; /* shortcut */
887
888 /* Get offset/length of blocks that actually point to a data elem,
889 until all blocks in this table with valid ref#s are processed */
890 for (ii = 0; ii < num_blocks && link_info->block_list[ii].ref != 0;ii++)
891 {
892 int32 offset, length;
893 uint16 block_ref = link_info->block_list[ii].ref; /* shortcut */
894
895 /* If this block has a valid ref# then get the offset/length of
896 the data if they are requested, and increment the number of
897 data blocks */
898 if (block_ref != 0)
899 {
900 if (offsetarray != NULL)
901 {
902 offset = Hoffset(file_id, DFTAG_LINKED, block_ref);
903 if (offset == FAIL)
904 HGOTO_ERROR(DFE_INTERNAL, FAIL);
905 offsetarray[num_data_blocks] = offset;
906 }
907 if (lengtharray != NULL)
908 {
909 length = Hlength(file_id, DFTAG_LINKED, block_ref);
910 if (length == FAIL)
911 HGOTO_ERROR(DFE_INTERNAL, FAIL);
912
913 /* Make sure to detect when the last block of the element is
914 reached and calculate the len of the actual data in it */
915
916 /* Continue accumulating data length if there is
917 another block table coming */
918 if (next_ref != 0)
919 accum_length = accum_length + length;
920
921 /* When no more block table following this one, i.e., this
922 is the last block table in the element */
923 else
924 {
925 /* if this is NOT the last block having data in the
926 current table, continue accumulating */
927 if (ii < num_blocks - 1 && link_info->block_list[ii + 1].ref != 0)
928 accum_length = accum_length + length;
929
930 /* else, i.e., this is the last block in the curr table,
931 or the last block that points to actual data */
932 else
933 {
934 /* then calculate the data's actual length when the
935 length is the same as the default block length,
936 because it might not be */
937 if (length == block_length)
938 length = total_length - accum_length;
939 }
940 }
941 /* Record the actual data length in the current block */
942 lengtharray[num_data_blocks] = length;
943 }
944 num_data_blocks++; /* count number of blocks with data */
945 }
946 } /* for each block in the current table */
947
948 /* Free allocated memory before getting the next block table if
949 there is one */
950 if (link_info != NULL)
951 {
952 if (link_info->block_list != NULL)
953 HDfree(link_info->block_list);
954 HDfree(link_info);
955 link_info = NULL;
956 }
957 /* Get next block table */
958 if (next_ref != 0)
959 link_info = HLIgetlink(file_id, next_ref, num_blocks);
960 } /* while there are more linked-block tables and the offset/length arrays
961 are not full yet */
962
963 /* Return the number of blocks with actual data */
964 ret_value = num_data_blocks;
965
966 done:
967 if(ret_value == FAIL)
968 { /* Error condition cleanup */
969 if(link_info != NULL)
970 if (link_info->block_list != NULL)
971 HDfree(link_info->block_list);
972 HDfree(link_info);
973 } /* end if */
974
975 /* Normal function cleanup */
976 return ret_value;
977 } /* HLgetdatainfo */
978
979 /* ------------------------------ HLPstread ------------------------------- */
980 /*
981 NAME
982 HLPstread -- open an access record for reading
983 USAGE
984 int32 HLPstread(access_rec)
985 access_t * access_rec; IN: access record to fill in
986 RETURNS
987 The AID of the access record on success FAIL on error.
988 DESCRIPTION
989 Calls to HLIstaccess to fill in the access rec for
990 reading
991
992 ---------------------------------------------------------------------------*/
993 int32
HLPstread(accrec_t * access_rec)994 HLPstread(accrec_t * access_rec)
995 {
996 int32 ret_value;
997
998 ret_value = HLIstaccess(access_rec, DFACC_READ);
999
1000 return ret_value;
1001 } /* HLPstread */
1002
1003 /* ------------------------------ HLPstwrite ------------------------------- */
1004 /*
1005 NAME
1006 HLPstwrite -- open an access record for writing
1007 USAGE
1008 int32 HLPstwrite(access_rec)
1009 access_t * access_rec; IN: access record to fill in
1010 RETURNS
1011 The AID of the access record on success FAIL on error.
1012 DESCRIPTION
1013 Calls to HLIstaccess to fill in the access rec for
1014 writing
1015
1016 ---------------------------------------------------------------------------*/
1017 int32
HLPstwrite(accrec_t * access_rec)1018 HLPstwrite(accrec_t * access_rec)
1019 {
1020 int32 ret_value;
1021
1022 ret_value = HLIstaccess(access_rec, (int16)DFACC_WRITE);
1023
1024 return ret_value;
1025 } /* HLPstwrite */
1026
1027 /* ------------------------------ HLIgetlink ------------------------------ */
1028 /*
1029 NAME
1030 HLIgetlink -- get link information
1031 USAGE
1032 link_t * HLIgetlink(fid, ref, num_blocks)
1033 int32 file_id; IN: the file
1034 uint16 ref; IN: ref number of the link table
1035 int32 num_blocks; IN: number of blocks in the table
1036 RETURNS
1037 A pointer to a link_t or NULL.
1038 DESCRIPTION
1039 Read a block table out of the file and return a pointer to
1040 the internal table representing it.
1041
1042 It seems that num_blocks is redundant.
1043
1044 ---------------------------------------------------------------------------*/
1045 PRIVATE link_t *
HLIgetlink(int32 file_id,uint16 ref,int32 number_blocks)1046 HLIgetlink(int32 file_id,
1047 uint16 ref,
1048 int32 number_blocks)
1049 {
1050 CONSTR(FUNC, "HLIgetlink"); /* for HERROR */
1051 int32 access_id; /* access record id */
1052 uint8 *buffer = NULL;
1053 uint16 tag = DFTAG_LINKED;
1054 link_t *new_link = NULL;
1055 link_t *ret_value = NULL; /* FAIL */
1056
1057 /* allocate necessary memory for in-memory block table */
1058 new_link = (link_t *) HDmalloc((uint32) sizeof(link_t));
1059
1060 if (new_link == NULL)
1061 HGOTO_ERROR(DFE_NOSPACE, NULL);
1062
1063 new_link->block_list = (block_t *) HDmalloc((uint32) number_blocks
1064 * sizeof(block_t));
1065 if (new_link->block_list == NULL)
1066 HGOTO_ERROR(DFE_NOSPACE, NULL);
1067
1068 new_link->next = (link_t *) NULL;
1069
1070 /* create temp buffer to read block table in */
1071 buffer = (uint8 *) HDmalloc((uint32) (2 + 2 * number_blocks));
1072 if (buffer == NULL)
1073 HGOTO_ERROR(DFE_NOSPACE, NULL);
1074
1075 /* read block table into buffer */
1076 access_id = Hstartread(file_id, tag, ref);
1077 if (access_id == FAIL ||
1078 Hread(access_id, 2 + 2 * number_blocks, buffer) == FAIL)
1079 HGOTO_ERROR(DFE_READERROR, NULL);
1080
1081 /* decode block table information read from file */
1082 {
1083 int32 i;
1084 uint8 *p = buffer;
1085
1086 UINT16DECODE(p, new_link->nextref);
1087 for (i = 0; i < number_blocks; i++)
1088 UINT16DECODE(p, new_link->block_list[i].ref);
1089 }
1090
1091 /* end acces to this block table */
1092 Hendaccess(access_id);
1093
1094 /* set return value */
1095 ret_value = new_link;
1096
1097 done:
1098 if(ret_value == NULL)
1099 { /* Error condition cleanup */
1100 if (new_link->block_list != NULL)
1101 HDfree(new_link->block_list);
1102 if (new_link != NULL)
1103 HDfree(new_link);
1104 } /* end if */
1105
1106 /* Normal function cleanup */
1107 if (buffer != NULL)
1108 HDfree(buffer);
1109
1110 return ret_value;
1111 } /* HLIgetlink */
1112
1113 /* ------------------------------- HLPseek -------------------------------- */
1114 /*
1115 NAME
1116 HLPseek -- set the seek posn
1117 USAGE
1118 int32 HLPseek(access_rec, offset, origin)
1119 access_t * access_rec; IN: access record to mess with
1120 int32 offset; IN: seek offset
1121 int32 origin; IN: where we should calc the offset from
1122 RETURNS
1123 SUCCEED / FAIL
1124 DESCRIPTION
1125 Set the seek posn in the given linked block element
1126
1127 ---------------------------------------------------------------------------*/
1128 int32
HLPseek(accrec_t * access_rec,int32 offset,int origin)1129 HLPseek(accrec_t *access_rec,
1130 int32 offset,
1131 int origin)
1132 {
1133 CONSTR(FUNC, "HLPseek"); /* for HERROR */
1134 int32 ret_value = SUCCEED;
1135
1136 /* validate access record */
1137 if (access_rec->special != SPECIAL_LINKED)
1138 HGOTO_ERROR(DFE_INTERNAL, FAIL);
1139
1140 /* adjust the offset according to origin and validate */
1141 /* there is no upper bound to posn */
1142 if (origin == DF_CURRENT)
1143 offset += access_rec->posn;
1144 if (origin == DF_END)
1145 offset += ((linkinfo_t *) (access_rec->special_info))->length;
1146 if (offset < 0)
1147 HGOTO_ERROR(DFE_RANGE, FAIL);
1148
1149 /* set position */
1150 access_rec->posn = offset;
1151
1152 done:
1153 if(ret_value == FAIL)
1154 { /* Error condition cleanup */
1155
1156 } /* end if */
1157
1158 /* Normal function cleanup */
1159
1160 return ret_value;
1161 } /* HLPseek */
1162
1163 /* ------------------------------- HLPread -------------------------------- */
1164 /*
1165 NAME
1166 HLPread -- read some data out of a linked block element
1167 USAGE
1168 int32 HLPseek(access_rec, length, data)
1169 access_t * access_rec; IN: access record to mess with
1170 int32 length; IN: number of bytes to read
1171 void * data; IN: buffer for data
1172 RETURNS
1173 The number of bytes read or FAIL on error
1174 DESCRIPTION
1175 Read in some data from a linked block element. If length
1176 is zero read until the end of the element. It is assumed
1177 that the data buffer is big enough to store the data.
1178 If length would take us off the end of the element only
1179 read what has been written.
1180
1181 --------------------------------------------------------------------------- */
1182 int32
HLPread(accrec_t * access_rec,int32 length,void * datap)1183 HLPread(accrec_t *access_rec,
1184 int32 length,
1185 void * datap)
1186 {
1187 CONSTR(FUNC, "HLPread"); /* for HERROR */
1188 uint8 *data = (uint8 *) datap;
1189 /* information record for this special data elt */
1190 linkinfo_t *info = (linkinfo_t *) (access_rec->special_info);
1191 link_t *t_link = info->link; /* block table record */
1192
1193 /* relative position in linked block of data elt */
1194 int32 relative_posn = access_rec->posn;
1195
1196 int32 block_idx; /* block table index of current block */
1197 int32 current_length; /* length of current block */
1198 int32 nbytes = 0; /* # bytes read on any single Hread() */
1199 int32 bytes_read = 0; /* total # bytes read for this call of HLIread */
1200 int32 ret_value = SUCCEED;
1201
1202 /* validate length */
1203 if (length == 0)
1204 length = info->length - access_rec->posn;
1205 else
1206 if (length < 0)
1207 HGOTO_ERROR(DFE_RANGE, FAIL);
1208
1209 if (access_rec->posn + length > info->length)
1210 length = info->length - access_rec->posn;
1211
1212 /* search for linked block to start reading from */
1213 if (relative_posn < info->first_length)
1214 { /* first block */
1215 block_idx = 0;
1216 current_length = info->first_length;
1217 }
1218 else /* not first block? */
1219 {
1220 relative_posn -= info->first_length;
1221 block_idx = relative_posn / info->block_length + 1;
1222 relative_posn %= info->block_length;
1223 current_length = info->block_length;
1224 }
1225
1226 /* calculate which block to start from? */
1227 {
1228 int32 i;
1229
1230 for (i = 0; i < block_idx / info->number_blocks; i++)
1231 {
1232 if (t_link == NULL)
1233 HGOTO_ERROR(DFE_INTERNAL, FAIL);
1234 t_link = t_link->next;
1235 }
1236 }
1237 block_idx %= info->number_blocks;
1238
1239 /* found the starting block, now read in the data */
1240 do
1241 {
1242 int32 remaining = /* remaining data in current block */
1243 current_length - relative_posn;
1244
1245 /* read in the data in this block */
1246 if (remaining > length)
1247 remaining = length;
1248 if (t_link->block_list[block_idx].ref != 0)
1249 {
1250 int32 access_id; /* access record id for this block */
1251 block_t *current_block = /* record on the current block */
1252 &(t_link->block_list[block_idx]);
1253
1254 access_id = Hstartread(access_rec->file_id, DFTAG_LINKED,
1255 current_block->ref);
1256 if (access_id == (int32) FAIL
1257 || (relative_posn
1258 && (int32) FAIL == Hseek(access_id, relative_posn, DF_START))
1259 || (int32) FAIL == (nbytes = Hread(access_id, remaining, data)))
1260 HGOTO_ERROR(DFE_READERROR, FAIL);
1261
1262 bytes_read += nbytes;
1263 Hendaccess(access_id);
1264 }
1265 else
1266 { /*if block is missing, fill this part of buffer with zero's */
1267 HDmemset(data, 0, (size_t)remaining);
1268 bytes_read += nbytes;
1269 }
1270
1271 /* move variables for the next block */
1272 data += remaining;
1273 length -= remaining;
1274 if (length > 0 && ++block_idx >= info->number_blocks)
1275 {
1276 block_idx = 0;
1277 t_link = t_link->next;
1278 if (t_link == NULL)
1279 HGOTO_ERROR(DFE_INTERNAL, FAIL);
1280 }
1281 relative_posn = 0;
1282 current_length = info->block_length;
1283 }
1284 while (length > 0); /* if still somemore to read in, repeat */
1285
1286 access_rec->posn += bytes_read;
1287 ret_value = bytes_read;
1288
1289 done:
1290 if(ret_value == FAIL)
1291 { /* Error condition cleanup */
1292
1293 } /* end if */
1294
1295 /* Normal function cleanup */
1296
1297 return ret_value;
1298 } /* HLPread */
1299
1300 /* ------------------------------- HLPwrite ------------------------------- */
1301 /*
1302 NAME
1303 HLPwrite -- write out some data to a linked block
1304 USAGE
1305 int32 HLPwrite(access_rec, length, data)
1306 access_t * access_rec; IN: access record to mess with
1307 int32 length; IN: number of bytes to write
1308 void * data; IN: buffer for data
1309 RETURNS
1310 The number of bytes written or FAIL on error
1311 DESCRIPTION
1312 Write out some data from a linked block element. If we write
1313 passed the end of the existing element new blocks are created
1314 as needed.
1315
1316 ---------------------------------------------------------------------------*/
1317 int32
HLPwrite(accrec_t * access_rec,int32 length,const void * datap)1318 HLPwrite(accrec_t *access_rec,
1319 int32 length,
1320 const void * datap)
1321 {
1322 CONSTR(FUNC, "HLPwrite"); /* for HERROR */
1323 const uint8 *data = datap;
1324 filerec_t *file_rec; /* file record */
1325 int32 dd_aid; /* AID for writing the special info */
1326 uint16 data_tag, data_ref; /* Tag/ref of the data in the file */
1327 linkinfo_t *info = /* linked blocks information record */
1328 (linkinfo_t *) (access_rec->special_info);
1329 link_t *t_link = /* ptr to link block table */
1330 info->link;
1331 int32 relative_posn = /* relative position in linked block */
1332 access_rec->posn;
1333 int32 block_idx; /* block table index of current block */
1334 link_t *prev_link = NULL; /* ptr to block table before current block table.
1335 for groking the offset of
1336 current block table */
1337 int32 current_length; /* length of current block */
1338 int32 nbytes = 0; /* #bytes written by any single Hwrite */
1339 int32 bytes_written = 0; /* total #bytes written by HLIwrite */
1340 uint8 local_ptbuf[4];
1341 int32 ret_value = SUCCEED;
1342
1343 /* convert file id to file record */
1344 file_rec = HAatom_object(access_rec->file_id);
1345
1346 /* validate length and file records */
1347 if (length <= 0)
1348 HGOTO_ERROR(DFE_RANGE, FAIL);
1349 if (BADFREC(file_rec))
1350 HGOTO_ERROR(DFE_INTERNAL, FAIL);
1351
1352 /* determine linked block and position to start writing into */
1353 /* determine where to start. Setup missing block tables
1354 along the way. */
1355 if (relative_posn < info->first_length)
1356 {
1357 block_idx = 0;
1358 current_length = info->first_length;
1359 }
1360 else
1361 {
1362 relative_posn -= info->first_length;
1363 block_idx = relative_posn / info->block_length + 1;
1364 relative_posn %= info->block_length;
1365 current_length = info->block_length;
1366 }
1367 {
1368 /* follow the links of block tables and create missing
1369 block tables along the way */
1370 int32 num_links; /* number of links to follow */
1371
1372 for (num_links = block_idx / info->number_blocks; num_links > 0; num_links--)
1373 {
1374 if (!t_link->next)
1375 { /* create missing link (block table) */
1376 t_link->nextref = Htagnewref(access_rec->file_id,DFTAG_LINKED);
1377 t_link->next = HLInewlink(access_rec->file_id,
1378 info->number_blocks, t_link->nextref, 0);
1379 if (!t_link->next)
1380 HGOTO_ERROR(DFE_NOSPACE,FAIL);
1381 { /* AA */
1382 /* update previous link with information about new link */
1383
1384 uint16 link_tag = DFTAG_LINKED;
1385 uint16 link_ref = /* ref of current link */
1386 (uint16) (prev_link != NULL ?
1387 prev_link->nextref : info->link_ref);
1388
1389 uint8 *p = local_ptbuf; /* temp buf ptr */
1390
1391 /* write file the updated portion of current link */
1392
1393 int32 link_id = /* access id for current link */
1394 Hstartwrite(access_rec->file_id, link_tag, link_ref, 0);
1395
1396 if (link_id == FAIL)
1397 HGOTO_ERROR(DFE_WRITEERROR, FAIL);
1398 UINT16ENCODE(p, t_link->nextref);
1399 if (Hwrite(link_id, 2, local_ptbuf) == FAIL)
1400 HGOTO_ERROR(DFE_WRITEERROR, FAIL);
1401 Hendaccess(link_id);
1402 } /* AA */
1403 } /* if not t_link->next */
1404
1405 /* move to the next link */
1406 prev_link = t_link;
1407 t_link = t_link->next;
1408 } /* end for */
1409 } /* end block statement(bad) */
1410
1411 block_idx %= info->number_blocks;
1412
1413 /* start writing in that block */
1414 do
1415 {
1416 int32 access_id; /* access record id */
1417 int32 remaining = /* remaining data length in this block */
1418 current_length - relative_posn;
1419 uint16 new_ref = 0; /* ref of newly created block */
1420
1421 /* determine length and write this block */
1422 if (remaining > length)
1423 remaining = length;
1424
1425 /* this block already exist, so just set up access to it */
1426 if (t_link->block_list[block_idx].ref != 0)
1427 {
1428 block_t *current_block = /* ptr to current block record */
1429 &(t_link->block_list[block_idx]);
1430
1431 access_id = Hstartwrite(access_rec->file_id, DFTAG_LINKED,
1432 current_block->ref, current_length);
1433 }
1434 else
1435 { /* block is missing, set up a new block */
1436 new_ref = Htagnewref(access_rec->file_id,DFTAG_LINKED);
1437 access_id = Hstartwrite(access_rec->file_id, DFTAG_LINKED,
1438 new_ref, current_length);
1439 }
1440
1441 if (access_id == (int32) FAIL)
1442 HGOTO_ERROR(DFE_WRITEERROR, FAIL);
1443
1444 if ((relative_posn &&
1445 (int32) FAIL == Hseek(access_id, relative_posn, DF_START)) ||
1446 (int32) FAIL == (nbytes = Hwrite(access_id, remaining, data)))
1447 {
1448 HGOTO_ERROR(DFE_WRITEERROR, FAIL);
1449 }
1450 Hendaccess(access_id);
1451 bytes_written += nbytes;
1452
1453 if (new_ref)
1454 { /* created a new block, so update the link/block table */
1455 uint16 link_tag = DFTAG_LINKED;
1456 uint16 link_ref = /* ref of the current link/block table */
1457 (uint16) (prev_link ? prev_link->nextref : info->link_ref);
1458 uint8 *p = /* temp buffer ptr */
1459 local_ptbuf;
1460 int32 link_id = /* access record id of the current
1461 link/block table */
1462 Hstartwrite(access_rec->file_id, link_tag, link_ref, 0);
1463
1464 if (link_id == FAIL)
1465 HGOTO_ERROR(DFE_WRITEERROR, FAIL);
1466 UINT16ENCODE(p, new_ref);
1467 if (Hseek(link_id, 2 + 2 * block_idx, DF_START) == FAIL)
1468 HGOTO_ERROR(DFE_SEEKERROR, FAIL);
1469 if (Hwrite(link_id, 2, local_ptbuf) == FAIL)
1470 HGOTO_ERROR(DFE_WRITEERROR, FAIL);
1471 Hendaccess(link_id);
1472
1473 /* update memory structure */
1474 t_link->block_list[block_idx].ref = new_ref;
1475 } /* if new_ref */
1476
1477 /* move ptrs and counters for next phase */
1478 data += remaining;
1479 length -= remaining;
1480
1481 if (length > 0 && ++block_idx >= info->number_blocks)
1482 { /* move to the next link/block table */
1483 block_idx = 0;
1484 if (!t_link->next)
1485 { /* create missing link/block table */
1486 t_link->nextref = Htagnewref(access_rec->file_id,DFTAG_LINKED);
1487 t_link->next = HLInewlink(access_rec->file_id,
1488 info->number_blocks, t_link->nextref, 0);
1489 if (!t_link->next)
1490 HGOTO_ERROR(DFE_NOSPACE, FAIL);
1491
1492 { /* BB */
1493 uint16 link_tag = DFTAG_LINKED;
1494 uint16 link_ref = /* ref of current link/block table */
1495 (uint16) (prev_link ? prev_link->nextref : info->link_ref);
1496 uint8 *p = /* temp buffer ptr */
1497 local_ptbuf;
1498 int32 link_id = /* access record id of
1499 current link/block table */
1500 Hstartwrite(access_rec->file_id, link_tag,
1501 link_ref, 0);
1502
1503 if (link_id == FAIL)
1504 HGOTO_ERROR(DFE_WRITEERROR, FAIL);
1505 UINT16ENCODE(p, t_link->nextref);
1506 if (Hwrite(link_id, 2, local_ptbuf) == FAIL)
1507 HGOTO_ERROR(DFE_WRITEERROR, FAIL);
1508 Hendaccess(link_id);
1509 } /* BB */
1510 } /* if not t_link->next */
1511
1512 /* move to the next link/block table */
1513 prev_link = t_link;
1514 t_link = t_link->next;
1515 } /* end if "length" */
1516
1517 /* update vars for next phase */
1518 relative_posn = 0;
1519 current_length = info->block_length;
1520 }
1521 while (length > 0);
1522
1523 /* update the info for the dataset */
1524 if(HTPinquire(access_rec->ddid,&data_tag,&data_ref,NULL,NULL)==FAIL)
1525 HGOTO_ERROR(DFE_INTERNAL, FAIL);
1526 if((dd_aid=Hstartaccess(access_rec->file_id,data_tag,data_ref,DFACC_WRITE))==FAIL)
1527 HGOTO_ERROR(DFE_CANTACCESS, FAIL);
1528 if (Hseek(dd_aid, 2, DF_START) == FAIL)
1529 HGOTO_ERROR(DFE_SEEKERROR, FAIL);
1530 {
1531 int32 tmp;
1532 uint8 *p = local_ptbuf;
1533
1534 tmp = bytes_written + access_rec->posn;
1535 if (tmp > info->length)
1536 info->length = tmp;
1537 INT32ENCODE(p, info->length);
1538
1539 }
1540 if (Hwrite(dd_aid, 4, local_ptbuf) == FAIL)
1541 HGOTO_ERROR(DFE_READERROR, FAIL);
1542 if(Hendaccess(dd_aid)==FAIL)
1543 HGOTO_ERROR(DFE_CANTENDACCESS, FAIL);
1544
1545 access_rec->posn += bytes_written;
1546 /* return SUCCEED; */
1547 /* if wrong # bytes written, FAIL has already been returned */
1548 ret_value = bytes_written;
1549
1550 done:
1551 if(ret_value == FAIL)
1552 { /* Error condition cleanup */
1553
1554 } /* end if */
1555
1556 /* Normal function cleanup */
1557
1558 return ret_value;
1559 } /* HLPwrite */
1560
1561 /* ------------------------------ HLInewlink ------------------------------ */
1562 /*
1563 NAME
1564 HLInewlink -- write out some data to a linked block
1565 USAGE
1566 link_t * HLInewlink(fid, nblocks, link_ref, first_block_ref)
1567 int32 fid; IN: file ID
1568 int32 nblocks; IN: number of blocks in the table
1569 uint16 link_ref; IN: ref number for the table
1570 uint16 first_block_ref; IN: ref number for first block
1571 RETURNS
1572 A pointer to a new link/block table or NULL
1573 DESCRIPTION
1574 Create a new link/block table in memory and in file returns
1575 ptr to the new link/block table.
1576
1577 ---------------------------------------------------------------------------*/
1578 PRIVATE link_t *
HLInewlink(int32 file_id,int32 number_blocks,uint16 link_ref,uint16 first_block_ref)1579 HLInewlink(int32 file_id,
1580 int32 number_blocks,
1581 uint16 link_ref,
1582 uint16 first_block_ref)
1583 {
1584 CONSTR(FUNC, "HLInewlink"); /* for HERROR */
1585 int32 link_id; /* access record id of new link */
1586 uint8 *buf = NULL; /* temp buffer */
1587 link_t *t_link = NULL;
1588 link_t *ret_value = NULL; /* FAIL */
1589
1590 /* set up new link record in memory */
1591 /* new link record */
1592 t_link = (link_t *) HDmalloc((uint32) sizeof(link_t));
1593
1594 if (!t_link)
1595 HGOTO_ERROR(DFE_NOSPACE, NULL);
1596
1597 t_link->block_list = (block_t *) HDmalloc((uint32) number_blocks
1598 * sizeof(block_t));
1599 if (!t_link->block_list)
1600 HGOTO_ERROR(DFE_NOSPACE, NULL);
1601
1602 t_link->next = NULL;
1603
1604 /* get ready to write the new link to file */
1605 link_id = Hstartwrite(file_id, DFTAG_LINKED, link_ref, 2 + 2 * number_blocks);
1606 if (link_id == FAIL)
1607 HGOTO_ERROR(DFE_WRITEERROR, NULL);
1608
1609 /* encode this block information for writing to the file */
1610 { /* CC */
1611 int32 i; /* temp int index */
1612 uint8 *p; /* temp buffer ptr */
1613
1614 p = buf = (uint8 *) HDmalloc((uint32) (2 + 2 * number_blocks));
1615 if (!buf)
1616 HGOTO_ERROR(DFE_NOSPACE, NULL);
1617
1618 /* set up the record and write to file */
1619 t_link->nextref = 0;
1620 UINT16ENCODE(p, 0);
1621 t_link->block_list[0].ref = first_block_ref;
1622 UINT16ENCODE(p, first_block_ref);
1623 /* why is this first_block_ref = 0? */
1624 for (i = 1; i < number_blocks; i++)
1625 { /* set up each block in this link */
1626 t_link->block_list[i].ref = 0;
1627 UINT16ENCODE(p, 0);
1628 }
1629 } /* CC */
1630
1631 /* write the link */
1632 if (Hwrite(link_id, 2 + 2 * number_blocks, buf) == FAIL)
1633 HGOTO_ERROR(DFE_WRITEERROR, NULL);
1634
1635 /* close down acces to this block */
1636 Hendaccess(link_id);
1637
1638 /* set return value */
1639 ret_value = t_link;
1640
1641 done:
1642 if(ret_value == NULL)
1643 { /* Error condition cleanup */
1644 if (t_link->block_list != NULL)
1645 HDfree(t_link->block_list);
1646 if (t_link != NULL)
1647 HDfree(t_link);
1648 } /* end if */
1649
1650 /* Normal function cleanup */
1651 if (buf != NULL)
1652 HDfree(buf);
1653
1654 return ret_value;
1655 } /* HLInewlink */
1656
1657 /* ------------------------------ HLPinquire ------------------------------ */
1658 /*
1659 NAME
1660 HLPinquire -- Hinquire for linked blocks
1661 USAGE
1662 int32 HLPinquire(access_rec, fid, tag, ref, len, off, pos, acc, sp)
1663 access_t * access_rec; IN: access record to return info about
1664 uint16 * file; OUT: file ID;
1665 uint16 * tag; OUT: tag of info record;
1666 uint16 * ref; OUT: ref of info record;
1667 int32 * len; OUT: length of element;
1668 int32 * off; OUT: offset of element -- meaningless
1669 int32 * pos; OUT: current position in element;
1670 int16 * acc; OUT: access mode;
1671 int16 * sp; OUT: special code;
1672 RETURNS
1673 SUCCEED
1674 DESCRIPTION
1675 Return interesting information about a linked block element.
1676 NULL can be passed for any of the OUT parameters if their
1677 value is not needed.
1678
1679 --------------------------------------------------------------------------- */
1680 int32
HLPinquire(accrec_t * access_rec,int32 * pfile_id,uint16 * ptag,uint16 * pref,int32 * plength,int32 * poffset,int32 * pposn,int16 * paccess,int16 * pspecial)1681 HLPinquire(accrec_t *access_rec,
1682 int32 *pfile_id,
1683 uint16 *ptag,
1684 uint16 *pref,
1685 int32 *plength,
1686 int32 *poffset,
1687 int32 *pposn,
1688 int16 *paccess,
1689 int16 *pspecial)
1690 {
1691 CONSTR(FUNC, "HLPinquire"); /* for HERROR */
1692 uint16 data_tag, data_ref; /* Tag/ref of the data in the file */
1693 linkinfo_t *info = /* special information record */
1694 (linkinfo_t *) access_rec->special_info;
1695 int32 ret_value = SUCCEED;
1696
1697 /* update the info for the dataset */
1698 if(HTPinquire(access_rec->ddid,&data_tag,&data_ref,NULL,NULL)==FAIL)
1699 HGOTO_ERROR(DFE_INTERNAL, FAIL);
1700
1701 /* fill in the variables if they are present */
1702 if (pfile_id)
1703 *pfile_id = access_rec->file_id;
1704 if (ptag)
1705 *ptag = data_tag;
1706 if (pref)
1707 *pref = data_ref;
1708 if (plength)
1709 *plength = info->length;
1710 if (poffset)
1711 *poffset = 0; /* meaningless */
1712 if (pposn)
1713 *pposn = access_rec->posn;
1714 if (paccess)
1715 *paccess = (int16)access_rec->access;
1716 if (pspecial)
1717 *pspecial = (int16)access_rec->special;
1718
1719 done:
1720 if(ret_value == FAIL)
1721 { /* Error condition cleanup */
1722
1723 } /* end if */
1724
1725 /* Normal function cleanup */
1726
1727 return ret_value;
1728 } /* HLPinquire */
1729
1730 /* ----------------------------- HLPendaccess ----------------------------- */
1731 /*
1732 NAME
1733 HLPendacess -- close a linked block AID
1734 USAGE
1735 intn HLPendaccess(access_rec)
1736 access_t * access_rec; IN: access record to close
1737 RETURNS
1738 SUCCEED / FAIL
1739 DESCRIPTION
1740 Free up all of the space used to store information about a
1741 linked block element. Information is flushed to disk as
1742 it is created so this routine does NOT have to write anything
1743 out.
1744
1745 --------------------------------------------------------------------------- */
1746 intn
HLPendaccess(accrec_t * access_rec)1747 HLPendaccess(accrec_t * access_rec)
1748 {
1749 CONSTR(FUNC, "HLPendaccess"); /* for HERROR */
1750 filerec_t *file_rec; /* file record */
1751 intn ret_value = SUCCEED;
1752
1753 /* validate argument */
1754 if (access_rec == NULL)
1755 HGOTO_ERROR(DFE_ARGS, FAIL);
1756
1757 /* convert file id to file record */
1758 file_rec = HAatom_object(access_rec->file_id);
1759 if (BADFREC(file_rec))
1760 HGOTO_ERROR(DFE_ARGS, FAIL);
1761
1762 /* detach the special information record.
1763 If no more references to that, free the record */
1764 if (HLPcloseAID(access_rec) == FAIL)
1765 HGOTO_ERROR(DFE_CANTCLOSE, FAIL);
1766
1767 /* update file and access records */
1768 if (HTPendaccess(access_rec->ddid) == FAIL)
1769 HGOTO_ERROR(DFE_CANTENDACCESS, FAIL);
1770
1771 /* detach from the file */
1772 file_rec->attach--;
1773
1774 /* free the access record */
1775 HIrelease_accrec_node(access_rec);
1776
1777 done:
1778 if(ret_value == FAIL)
1779 { /* Error condition cleanup */
1780 if(access_rec!=NULL)
1781 HIrelease_accrec_node(access_rec);
1782 } /* end if */
1783
1784 /* Normal function cleanup */
1785
1786 return ret_value;
1787 } /* HLPendaccess */
1788
1789 /* ----------------------------- HLPcloseAID ------------------------------ */
1790 /*
1791 NAME
1792 HLPcloseAID -- close file but keep AID active
1793 USAGE
1794 int32 HLPcloseAID(access_rec)
1795 access_t * access_rec; IN: access record of file to close
1796 RETURNS
1797 SUCCEED / FAIL
1798 DESCRIPTION
1799 close the file currently being pointed to by this AID but
1800 do *NOT* free the AID.
1801
1802 This is called by Hnextread() which reuses an AID to point to
1803 the 'next' object as requested. If the current object was an
1804 linked object, the linked information needs to be closed before all
1805 reference to it is lost.
1806
1807 ---------------------------------------------------------------------------*/
1808 int32
HLPcloseAID(accrec_t * access_rec)1809 HLPcloseAID(accrec_t * access_rec)
1810 {
1811 #ifdef LATER
1812 CONSTR(FUNC, "HLPcloseAID"); /* for HERROR */
1813 #endif /* LATER */
1814 linkinfo_t *info = /* special information record */
1815 (linkinfo_t *) access_rec->special_info;
1816 int32 ret_value = SUCCEED;
1817
1818 /* detach the special information record.
1819 If no more references to that, free the record */
1820 if (--(info->attached) == 0)
1821 {
1822 link_t *t_link; /* current link to free */
1823 link_t *next; /* next link to free */
1824
1825 /* free the linked list of links/block tables */
1826 for (t_link = info->link; t_link; t_link = next)
1827 {
1828 next = t_link->next;
1829 HDfree(t_link->block_list);
1830 HDfree(t_link);
1831 }
1832
1833 HDfree(info);
1834 access_rec->special_info = NULL;
1835 }
1836
1837 #ifdef LATER
1838 done:
1839 #endif /* LATER */
1840 if(ret_value == FAIL)
1841 { /* Error condition cleanup */
1842
1843 } /* end if */
1844
1845 /* Normal function cleanup */
1846
1847 return ret_value;
1848 } /* HLPcloseAID */
1849
1850 /* ------------------------------- HLPinfo -------------------------------- */
1851 /*
1852 NAME
1853 HLPinfo -- return info about a linked block element
1854 USAGE
1855 int32 HLPinfo(access_rec, info_block)
1856 access_t * access_rec;
1857 IN: access record of access element
1858 sp_info_block_t * info_block;
1859 OUT: information about the special element
1860 RETURNS
1861 SUCCEED / FAIL
1862 DESCRIPTION
1863 Return information about the given linked block. Info_block is
1864 assumed to be non-NULL.
1865
1866 --------------------------------------------------------------------------- */
1867 int32
HLPinfo(accrec_t * access_rec,sp_info_block_t * info_block)1868 HLPinfo(accrec_t * access_rec, sp_info_block_t * info_block)
1869 {
1870 CONSTR(FUNC, "HLPinfo");
1871 linkinfo_t *info = /* special information record */
1872 (linkinfo_t *) access_rec->special_info;
1873 int32 ret_value = SUCCEED;
1874
1875 /* validate access record */
1876 if (access_rec->special != SPECIAL_LINKED)
1877 HGOTO_ERROR(DFE_INTERNAL, FAIL);
1878
1879 /* fill in the info_block */
1880 info_block->key = SPECIAL_LINKED;
1881
1882 info_block->first_len = info->first_length;
1883 info_block->block_len = info->block_length;
1884 info_block->nblocks = info->number_blocks;
1885
1886 done:
1887 if(ret_value == FAIL)
1888 { /* Error condition cleanup */
1889
1890 } /* end if */
1891
1892 /* Normal function cleanup */
1893
1894 return ret_value;
1895 } /* HLPinfo */
1896
1897 /*--------------------------------------------------------------------------
1898 NAME
1899 HLsetblockinfo -- set the block length of a linked-block element
1900
1901 USAGE
1902 intn HLsetblockinfo(
1903 int32 aid IN: access record id
1904 int32 block_size IN: length to be used for each linked-block
1905 int32 num_blocks IN: number of blocks the element will have
1906
1907 RETURNS
1908 SUCCEED / FAIL
1909
1910 DESCRIPTION
1911 HLsetblockinfo sets (accrec_t).block_size and (accrec_t).num_blocks
1912 to block_size and num_blocks, respectively. An error will occur, if
1913 either of the parameters is a 0 or a negative number, that is not
1914 -1, which is used to indicate that the respective field is not to be
1915 changed.
1916
1917 In the library, this routine is used by:
1918 VSsetblocksize
1919 VSsetnumblocks
1920
1921 MODIFICATION
1922 BMR - added in June 2001 to fix bug# 267
1923
1924 --------------------------------------------------------------------------*/
1925 intn
HLsetblockinfo(int32 aid,int32 block_size,int32 num_blocks)1926 HLsetblockinfo(int32 aid, /* access record id */
1927 int32 block_size, /* length to be used for each linked-block */
1928 int32 num_blocks) /* number of blocks the element will have */
1929 {
1930 CONSTR(FUNC, "HLsetblockinfo"); /* for HERROR */
1931 accrec_t *access_rec; /* access record */
1932 intn ret_value = SUCCEED;
1933
1934 /* clear error stack */
1935 HEclear();
1936
1937 /* validate aid */
1938 if (HAatom_group(aid)!=AIDGROUP)
1939 HGOTO_ERROR(DFE_ARGS, FAIL);
1940
1941 /* block_size and num_blocks should be either -1, to keep the original
1942 values, or positive values to change the block size and/or the
1943 number of blocks */
1944 if ((block_size <= 0 && block_size != -1) ||
1945 (num_blocks <= 0 && num_blocks != -1))
1946 HGOTO_ERROR(DFE_ARGS, FAIL);
1947
1948 /* get the access record */
1949 if ((access_rec = HAatom_object(aid)) == NULL)
1950 HGOTO_ERROR(DFE_ARGS, FAIL);
1951
1952 /* If this element is already stored as linked-block, do not allow
1953 to change the block info, ignore the request to change. */
1954 if (access_rec->special != SPECIAL_LINKED)
1955 {
1956 /* Set the linked-block size, if requested */
1957 if (block_size != -1)
1958 access_rec->block_size = block_size;
1959
1960 /* Set the number of blocks in each block table, if requested */
1961 if (num_blocks != -1)
1962 access_rec->num_blocks = num_blocks;
1963 }
1964
1965 done:
1966 if(ret_value == FAIL)
1967 { /* Error condition cleanup */
1968 } /* end if */
1969
1970 /* Normal function cleanup */
1971 return ret_value;
1972 } /* end HLsetblockinfo */
1973
1974 /*--------------------------------------------------------------------------
1975 NAME
1976 HLgetblockinfo -- get the block size and the number of blocks of a
1977 linked-block element
1978
1979 USAGE
1980 intn HLgetblockinfo(aid, block_size, num_blocks)
1981 int32 aid IN: access record id
1982 int32* block_size OUT: the returned block size of each linked-block
1983 int32* num_blocks OUT: the returned number of blocks of the element
1984
1985 RETURNS
1986 SUCCEED / FAIL
1987
1988 DESCRIPTION
1989 HLgetblockinfo retrieves the values of (accrec_t).block_size and
1990 (accrec_t).num_blocks to block_size and num_blocks, respectively.
1991 A NULL can be passed in for an unwanted value.
1992
1993 In the library, this routine is used by:
1994 VSgetblockinfo
1995
1996 MODIFICATION
1997 BMR - added in June 2001 to fix bug# 267
1998
1999 --------------------------------------------------------------------------*/
2000 intn
HLgetblockinfo(int32 aid,int32 * block_size,int32 * num_blocks)2001 HLgetblockinfo(int32 aid, /* access record id */
2002 int32* block_size, /* length being used for each linked-block */
2003 int32* num_blocks) /* number of blocks the element will have */
2004 {
2005 CONSTR(FUNC, "HLgetblockinfo"); /* for HERROR */
2006 accrec_t *access_rec; /* access record */
2007 intn ret_value = SUCCEED;
2008
2009 /* clear error stack */
2010 HEclear();
2011
2012 /* get the access record */
2013 if ((access_rec = HAatom_object(aid)) == NULL)
2014 HGOTO_ERROR(DFE_ARGS, FAIL);
2015
2016 /* get the linked-block size and the number of linked-blocks if requested */
2017 if (block_size != NULL)
2018 *block_size = access_rec->block_size;
2019 if (num_blocks != NULL)
2020 *num_blocks = access_rec->num_blocks;
2021
2022 done:
2023 if(ret_value == FAIL)
2024 { /* Error condition cleanup */
2025
2026 } /* end if */
2027
2028 /* Normal function cleanup */
2029 return ret_value;
2030 } /* end HLgetblockinfo */
2031
2032