2 * Copyright (c) 1990 The Regents of the University of California.
5 * This code is derived from software contributed to Berkeley by
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 #if defined(LIBC_SCCS) && !defined(lint)
38 static char sccsid
[] = "@(#)dynahash.c 5.14 (Berkeley) 4/2/91";
39 #endif /* LIBC_SCCS and not lint */
41 #include <sys/param.h>
53 /* Fast arithmetic, relying on powers of 2, */
55 #define MOD(x,y) ((x) & ((y)-1))
56 #define RETURN_ERROR(ERR,LOC) { save_errno = ERR; goto LOC; }
65 extern int __get_page();
66 extern int __split_page();
68 extern int __delpair();
69 extern u_long
*__init_bitmap();
72 extern int __big_return();
73 extern int __big_keydata();
74 extern u_short
__find_last_page();
77 extern BUFHEAD
*__get_buf();
78 extern void __buf_init();
79 extern int __buf_free();
82 extern int (*default_hash
)();
85 extern int __expand_table();
86 extern u_int
__call_hash();
88 /* Internal routines */
89 static HTAB
*init_hash();
90 static int hash_access();
91 static int flush_meta();
92 static int alloc_segs();
93 static int init_htab();
94 static char *hash_realloc();
95 static int hdestroy();
96 static int hash_put();
97 static int hash_delete();
98 static int hash_get();
99 static int hash_sync();
100 static int hash_close();
101 static int hash_seq();
102 static void swap_header_copy();
103 static void swap_header();
109 #ifdef HASH_STATISTICS
110 long hash_accesses
, hash_collisions
, hash_expansions
, hash_overflows
;
113 /************************** INTERFACE ROUTINES **********************/
117 hash_open ( file
, flags
, mode
, info
)
121 const HASHINFO
*info
; /* Special directives for create */
135 if ( !(hashp
= (HTAB
*) calloc( 1, sizeof(HTAB
) ))) {
136 /* calloc should set errno */
141 Select flags relevant to us.
142 Even if user wants write only, we need to be able to read
143 the actual file, so we need to open it read/write. But, the
144 field in the hashp structure needs to be accurate so that
145 we can check accesses.
147 flags
= flags
& (O_CREAT
| O_EXCL
| O_RDONLY
| O_RDWR
| O_TRUNC
| O_WRONLY
);
148 hashp
->flags
= flags
;
149 if ( flags
& O_WRONLY
) flags
= (flags
& ~O_WRONLY
) | O_RDWR
;
153 (stat ( file
, &statbuf
) && (errno
== ENOENT
)) ) {
154 if ( errno
== ENOENT
) {
155 errno
= 0; /* Just in case someone looks at errno */
161 if ((hashp
->fp
= open ( file
, flags
, mode
)) == -1) {
162 RETURN_ERROR (errno
, error0
);
164 (void)fcntl(hashp
->fp
, F_SETFD
, 1);
168 if ( !(hashp
= init_hash( info
)) ) {
169 RETURN_ERROR(errno
,error1
);
172 /* Table already exists */
173 if ( info
&& info
->hash
) hashp
->hash
= info
->hash
;
174 else hashp
->hash
= default_hash
;
176 hdrsize
= read ( hashp
->fp
, &hashp
->hdr
, sizeof(HASHHDR
) );
177 #if BYTE_ORDER == LITTLE_ENDIAN
180 if ( hdrsize
== -1 ) {
181 RETURN_ERROR(errno
, error1
);
183 if ( hdrsize
!= sizeof(HASHHDR
) ) {
184 RETURN_ERROR(EFTYPE
, error1
);
187 /* Verify file type, versions and hash function */
188 if ( hashp
->MAGIC
!= HASHMAGIC
)
189 RETURN_ERROR ( EFTYPE
, error1
);
190 if ( hashp
->VERSION
!= VERSION_NO
)
191 RETURN_ERROR ( EFTYPE
, error1
);
192 if (hashp
->hash ( CHARKEY
, sizeof(CHARKEY
) ) != hashp
->H_CHARKEY
) {
193 RETURN_ERROR ( EFTYPE
, error1
);
197 Figure out how many segments we need.
199 nsegs
= (hashp
->MAX_BUCKET
+ hashp
->SGSIZE
-1)/ hashp
->SGSIZE
;
201 if (alloc_segs( nsegs
)) {
203 If alloc_segs fails, table will have been destroyed
204 and errno will have been set.
206 return( (DB
*) NULL
);
209 /* Read in bitmaps */
210 bpages
= (hashp
->SPARES
[__log2(hashp
->MAX_BUCKET
)] +
211 (hashp
->BSIZE
<< BYTE_SHIFT
) - 1) >>
212 (hashp
->BSHIFT
+ BYTE_SHIFT
);
214 hashp
->nmaps
= bpages
;
215 memset ( &hashp
->mapp
[0], 0, bpages
* sizeof ( u_long
*) );
218 /* Initialize Buffer Manager */
219 if ( info
&& info
->cachesize
) {
220 __buf_init (info
->cachesize
);
222 __buf_init (DEF_BUFSIZE
);
225 hashp
->new_file
= new_table
;
226 hashp
->save_file
= file
&& (hashp
->flags
& (O_WRONLY
|O_RDWR
));
228 if ( !(dbp
= (DB
*)malloc ( sizeof (DB
) )) ) {
234 dbp
->internal
= (char *)hashp
;
235 dbp
->close
= hash_close
;
236 dbp
->del
= hash_delete
;
240 dbp
->sync
= hash_sync
;
244 (void)fprintf(stderr
, "%s\n%s%x\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n",
246 "TABLE POINTER ", hashp
,
247 "BUCKET SIZE ", hashp
->BSIZE
,
248 "BUCKET SHIFT ", hashp
->BSHIFT
,
249 "DIRECTORY SIZE ", hashp
->DSIZE
,
250 "SEGMENT SIZE ", hashp
->SGSIZE
,
251 "SEGMENT SHIFT ", hashp
->SSHIFT
,
252 "FILL FACTOR ", hashp
->FFACTOR
,
253 "MAX BUCKET ", hashp
->MAX_BUCKET
,
254 "HIGH MASK ", hashp
->HIGH_MASK
,
255 "LOW MASK ", hashp
->LOW_MASK
,
256 "NSEGS ", hashp
->nsegs
,
257 "NKEYS ", hashp
->NKEYS
);
259 #ifdef HASH_STATISTICS
260 hash_overflows
= hash_accesses
= hash_collisions
= hash_expansions
= 0;
267 return ( (DB
*)NULL
);
270 (void) close ( hashp
->fp
);
275 return ( (DB
*) NULL
);
287 hashp
= (HTAB
*)dbp
->internal
;
294 /************************** LOCAL CREATION ROUTINES **********************/
303 hashp
->LORDER
= BYTE_ORDER
;
304 hashp
->BSIZE
= DEF_BUCKET_SIZE
;
305 hashp
->BSHIFT
= DEF_BUCKET_SHIFT
;
306 hashp
->SGSIZE
= DEF_SEGSIZE
;
307 hashp
->SSHIFT
= DEF_SEGSIZE_SHIFT
;
308 hashp
->DSIZE
= DEF_DIRSIZE
;
309 hashp
->FFACTOR
= DEF_FFACTOR
;
310 hashp
->hash
= default_hash
;
311 bzero (hashp
->SPARES
, sizeof (hashp
->SPARES
));
315 /* Round pagesize up to power of 2 */
316 hashp
->BSHIFT
= __log2(info
->bsize
);
317 hashp
->BSIZE
= 1 << hashp
->BSHIFT
;
318 if ( hashp
->BSIZE
> MAX_BSIZE
) {
323 if ( info
->ffactor
) hashp
->FFACTOR
= info
->ffactor
;
324 if ( info
->hash
) hashp
->hash
= info
->hash
;
325 if ( info
->nelem
) nelem
= info
->nelem
;
326 if ( info
->lorder
) {
327 if ( info
->lorder
!= BIG_ENDIAN
&&
328 info
->lorder
!= LITTLE_ENDIAN
) {
332 hashp
->LORDER
= info
->lorder
;
336 /* init_htab should destroy the table and set errno if it fails */
337 if ( init_htab ( nelem
) ) {
345 This calls alloc_segs which may run out of memory.
346 Alloc_segs will destroy the table and set errno,
347 so we just pass the error information along.
349 Returns 0 on No Error
356 register SEGMENT
*segp
;
357 register int nbuckets
;
362 * Divide number of elements by the fill factor and determine a desired
363 * number of buckets. Allocate space for the next greater power of
364 * two number of buckets
366 nelem
= (nelem
- 1) / hashp
->FFACTOR
+ 1;
370 nbuckets
= MAX ( nbuckets
, 2 );
372 hashp
->SPARES
[l2
] = l2
+ 1;
373 hashp
->SPARES
[l2
+1] = l2
+ 1;
375 First bitmap page is at:
379 __init_bitmap ( OADDR_OF(l2
,1), l2
+1, 0 );
381 hashp
->MAX_BUCKET
= hashp
->LOW_MASK
= nbuckets
- 1;
382 hashp
->HIGH_MASK
= (nbuckets
<< 1) - 1;
383 hashp
->HDRPAGES
= ((MAX(sizeof(HASHHDR
),MINHDRSIZE
) - 1) >>
386 nsegs
= (nbuckets
- 1) / hashp
->SGSIZE
+ 1;
387 nsegs
= 1 << __log2(nsegs
);
389 if ( nsegs
> hashp
->DSIZE
) {
390 hashp
->DSIZE
= nsegs
;
393 return (alloc_segs ( nsegs
) );
396 /********************** DESTROY/CLOSE ROUTINES ************************/
399 Flushes any changes to the file if necessary and
400 destroys the hashp structure, freeing all allocated
412 #ifdef HASH_STATISTICS
413 (void) fprintf(stderr
, "hdestroy: accesses %ld collisions %ld\n",
414 hash_accesses
, hash_collisions
);
415 (void) fprintf(stderr
, "hdestroy: expansions %ld\n",
417 (void) fprintf(stderr
, "hdestroy: overflows %ld\n",
419 (void) fprintf(stderr
, "keys %ld maxp %d segmentcount %d\n",
420 hashp
->NKEYS
, hashp
->MAX_BUCKET
, hashp
->nsegs
);
422 for ( i
= 0; i
< NCACHED
; i
++ ) {
423 (void) fprintf ( stderr
, "spares[%d] = %d\n", i
, hashp
->SPARES
[i
] );
428 Call on buffer manager to free buffers, and if
429 required, write them to disk
431 if (__buf_free(1, hashp
->save_file
)) {
435 (void)free(*hashp
->dir
); /* Free initial segments */
436 /* Free extra segments */
437 while ( hashp
->exsegs
-- ) {
438 (void)free ( hashp
->dir
[--hashp
->nsegs
] );
440 (void)free(hashp
->dir
);
442 if (flush_meta() && !save_errno
) {
447 for ( i
= 0; i
< hashp
->nmaps
; i
++ ) {
448 if ( hashp
->mapp
[i
] ) {
449 (void) free ( hashp
->mapp
[i
] );
453 if ( hashp
->fp
!= -1 ) {
454 (void)close (hashp
->fp
);
468 Write modified pages to disk
480 hashp
= (HTAB
*)dbp
->internal
;
482 if (!hashp
->save_file
) return(0);
483 if ( __buf_free ( 0, 1 ) || flush_meta()) {
492 -1 indicates that errno should be set
504 if (!hashp
->save_file
) return(0);
505 hashp
->MAGIC
= HASHMAGIC
;
506 hashp
->VERSION
= VERSION_NO
;
507 hashp
->H_CHARKEY
= hashp
->hash ( CHARKEY
, sizeof(CHARKEY
));
511 #if BYTE_ORDER == LITTLE_ENDIAN
513 swap_header_copy( &hashp
->hdr
, whdrp
);
515 if ( (lseek (fp
, 0, SEEK_SET
) == -1 ) ||
516 ((wsize
= write ( fp
, whdrp
, sizeof(HASHHDR
))) == -1)) {
518 } else if ( wsize
!= sizeof(HASHHDR
) ) {
520 hashp
->errno
= errno
;
523 for ( i
= 0; i
< NCACHED
; i
++ ) {
524 if ( hashp
->mapp
[i
] ) {
525 if (!__put_page((char *)hashp
->mapp
[i
],
526 hashp
->BITMAPS
[i
], 0, 1)){
533 /*******************************SEARCH ROUTINES *****************************/
535 All the access routines return
537 1 to indicate an external ERROR (i.e. key not found, etc)
538 -1 to indicate an internal ERROR (i.e. out of memory, etc)
541 hash_get ( dbp
, key
, data
, flag
)
553 hashp
= (HTAB
*)dbp
->internal
;
554 if ( hashp
->flags
& O_WRONLY
) {
556 hashp
->errno
= errno
;
559 return ( hash_access ( HASH_GET
, key
, data
) );
563 hash_put ( dbp
, key
, data
, flag
)
571 hashp
= (HTAB
*)dbp
->internal
;
572 if ( (hashp
->flags
& O_ACCMODE
) == O_RDONLY
) {
574 hashp
->errno
= errno
;
577 if ( flag
== R_NOOVERWRITE
) {
578 return ( hash_access ( HASH_PUTNEW
, key
, data
) );
580 return ( hash_access ( HASH_PUT
, key
, data
) );
585 hash_delete ( dbp
, key
, flag
)
588 u_int flag
; /* Ignored */
596 hashp
= (HTAB
*)dbp
->internal
;
597 if ( (hashp
->flags
& O_ACCMODE
) == O_RDONLY
) {
599 hashp
->errno
= errno
;
602 return ( hash_access ( HASH_DELETE
, key
, NULL
) );
606 Assume that hashp has been set in wrapper routine
609 hash_access(action
, key
, val
)
613 register BUFHEAD
*rbufp
;
614 register u_short
*bp
;
617 register int off
= hashp
->BSIZE
;
624 #ifdef HASH_STATISTICS
629 kp
= (char *)key
->data
;
630 rbufp
= __get_buf ( __call_hash(kp
, size
), NULL
, 0 );
631 if ( !rbufp
) return(ERROR
);
634 /* Pin the bucket chain */
635 rbufp
->flags
|= BUF_PIN
;
636 for ( bp
= (u_short
*)rbufp
->page
, n
= *bp
++, ndx
= 1; ndx
< n
; ) {
637 if ( bp
[1] >= REAL_KEY
) {
638 /* Real key/data pair */
639 if (size
== off
- *bp
&&
640 bcmp(kp
, rbufp
->page
+ *bp
, size
) == 0) {
644 #ifdef HASH_STATISTICS
649 } else if ( bp
[1] == OVFLPAGE
) {
650 rbufp
= __get_buf ( *bp
, rbufp
, 0 );
652 save_bufp
->flags
&= ~BUF_PIN
;
656 bp
= (u_short
*)rbufp
->page
;
660 } else if ( bp
[1] < REAL_KEY
) {
661 if ( (ndx
= __find_bigpair(rbufp
, ndx
, kp
, size
)) > 0 ) {
663 } else if ( ndx
== -2 ) {
665 if ( !(pageno
= __find_last_page ( &bufp
)) ) {
670 rbufp
= __get_buf ( pageno
, bufp
, 0 );
672 save_bufp
->flags
&= ~BUF_PIN
;
676 bp
= (u_short
*)rbufp
->page
;
681 save_bufp
->flags
&= ~BUF_PIN
;
691 if (__addel(rbufp
, key
, val
)) {
692 save_bufp
->flags
&= ~BUF_PIN
;
695 save_bufp
->flags
&= ~BUF_PIN
;
701 save_bufp
->flags
&= ~BUF_PIN
;
708 save_bufp
->flags
&= ~BUF_PIN
;
711 bp
= (u_short
*)rbufp
->page
;
712 if (bp
[ndx
+1] < REAL_KEY
) __big_return(rbufp
, ndx
, val
, 0);
714 val
->data
= (u_char
*)rbufp
->page
+ (int) bp
[ndx
+ 1];
715 val
->size
= bp
[ndx
] - bp
[ndx
+ 1];
719 if ((__delpair (rbufp
, ndx
)) || (__addel (rbufp
, key
, val
)) ) {
720 save_bufp
->flags
&= ~BUF_PIN
;
725 if (__delpair (rbufp
, ndx
))return(ERROR
);
728 save_bufp
->flags
&= ~BUF_PIN
;
733 hash_seq(dbp
, key
, data
, flag
)
738 register u_int bucket
;
739 register BUFHEAD
*bufp
;
749 hashp
= (HTAB
*)dbp
->internal
;
750 if ( hashp
->flags
& O_WRONLY
) {
752 hashp
->errno
= errno
;
755 #ifdef HASH_STATISTICS
759 if ( (hashp
->cbucket
< 0) || (flag
== R_FIRST
) ) {
765 if ( !(bufp
= hashp
->cpage
) ) {
766 for (bucket
= hashp
->cbucket
;
767 bucket
<= hashp
->MAX_BUCKET
;
768 bucket
++, hashp
->cndx
= 1 ) {
770 bufp
= __get_buf ( bucket
, NULL
, 0 );
771 if (!bufp
) return(ERROR
);
773 bp
= (u_short
*)bufp
->page
;
776 hashp
->cbucket
= bucket
;
777 if ( hashp
->cbucket
> hashp
->MAX_BUCKET
) {
782 bp
= (u_short
*)hashp
->cpage
->page
;
789 while ( bp
[hashp
->cndx
+1] == OVFLPAGE
) {
790 bufp
= hashp
->cpage
= __get_buf ( bp
[hashp
->cndx
], bufp
, 0 );
791 if (!bufp
) return(ERROR
);
792 bp
= (u_short
*)(bufp
->page
);
796 if (bp
[ndx
+1] < REAL_KEY
) {
797 if (__big_keydata(bufp
, ndx
, key
, data
, 1)) {
801 key
->data
= (u_char
*)hashp
->cpage
->page
+ bp
[ndx
];
802 key
->size
= (ndx
> 1 ? bp
[ndx
-1] : hashp
->BSIZE
) - bp
[ndx
];
803 data
->data
= (u_char
*)hashp
->cpage
->page
+ bp
[ndx
+ 1];
804 data
->size
= bp
[ndx
] - bp
[ndx
+ 1];
810 } else hashp
->cndx
= ndx
;
815 /********************************* UTILITIES ************************/
823 u_int old_bucket
, new_bucket
;
827 register char **old
, **new;
828 #ifdef HASH_STATISTICS
832 new_bucket
= ++hashp
->MAX_BUCKET
;
833 old_bucket
= (hashp
->MAX_BUCKET
& hashp
->LOW_MASK
);
835 new_segnum
= new_bucket
>> hashp
->SSHIFT
;
837 /* Check if we need a new segment */
838 if ( new_segnum
>= hashp
->nsegs
) {
840 /* Check if we need to expand directory */
841 if ( new_segnum
>= hashp
->DSIZE
) {
843 /* Reallocate directory */
844 dirsize
= hashp
->DSIZE
* sizeof ( SEGMENT
* );
845 if (!hash_realloc ( &hashp
->dir
, dirsize
, (dirsize
<< 1 ) )) {
848 hashp
->DSIZE
= dirsize
<< 1;
850 if (!(hashp
->dir
[new_segnum
] =
851 (SEGMENT
)calloc ( hashp
->SGSIZE
, sizeof(SEGMENT
)))) {
859 If the split point is increasing (MAX_BUCKET's log
860 base 2 increases), we need to copy the current contents
861 of the spare split bucket to the next bucket
863 spare_ndx
= __log2(hashp
->MAX_BUCKET
);
864 if ( spare_ndx
!= (__log2(hashp
->MAX_BUCKET
- 1))) {
865 hashp
->SPARES
[spare_ndx
] = hashp
->SPARES
[spare_ndx
-1];
868 if ( new_bucket
> hashp
->HIGH_MASK
) {
869 /* Starting a new doubling */
870 hashp
->LOW_MASK
= hashp
->HIGH_MASK
;
871 hashp
->HIGH_MASK
= new_bucket
| hashp
->LOW_MASK
;
875 * Relocate records to the new bucket
877 return(__split_page ( old_bucket
, new_bucket
));
880 If realloc guarantees that the pointer is not destroyed
881 if the realloc fails, then this routine can go away
884 hash_realloc ( p_ptr
, oldsize
, newsize
)
891 if (p
= (char *)malloc ( newsize
) ) {
892 bcopy ( *p_ptr
, p
, oldsize
);
893 bzero ( *p_ptr
+ oldsize
, newsize
-oldsize
);
901 __call_hash ( k
, len
)
906 n
= hashp
->hash(k
, len
);
908 bucket
= n
& hashp
->HIGH_MASK
;
909 if ( bucket
> hashp
->MAX_BUCKET
) {
910 bucket
= bucket
& hashp
->LOW_MASK
;
917 Allocate segment table. On error, destroy the table
927 register SEGMENT store
;
931 if (!(hashp
->dir
= (SEGMENT
*)calloc(hashp
->DSIZE
, sizeof(SEGMENT
*)))) {
938 /* Allocate segments */
939 store
= (SEGMENT
)calloc ( nsegs
<< hashp
->SSHIFT
, sizeof (SEGMENT
) );
947 for ( i
=0; i
< nsegs
; i
++, hashp
->nsegs
++ ) {
948 hashp
->dir
[i
] = &store
[i
<<hashp
->SSHIFT
];
954 Hashp->hdr needs to be byteswapped.
957 swap_header_copy ( srcp
, destp
)
963 BLSWAP_COPY(srcp
->magic
, destp
->magic
);
964 BLSWAP_COPY(srcp
->version
, destp
->version
);
965 BLSWAP_COPY(srcp
->lorder
, destp
->lorder
);
966 BLSWAP_COPY(srcp
->bsize
, destp
->bsize
);
967 BLSWAP_COPY(srcp
->bshift
, destp
->bshift
);
968 BLSWAP_COPY(srcp
->dsize
, destp
->dsize
);
969 BLSWAP_COPY(srcp
->ssize
, destp
->ssize
);
970 BLSWAP_COPY(srcp
->sshift
, destp
->sshift
);
971 BLSWAP_COPY(srcp
->max_bucket
, destp
->max_bucket
);
972 BLSWAP_COPY(srcp
->high_mask
, destp
->high_mask
);
973 BLSWAP_COPY(srcp
->low_mask
, destp
->low_mask
);
974 BLSWAP_COPY(srcp
->ffactor
, destp
->ffactor
);
975 BLSWAP_COPY(srcp
->nkeys
, destp
->nkeys
);
976 BLSWAP_COPY(srcp
->hdrpages
, destp
->hdrpages
);
977 BLSWAP_COPY(srcp
->h_charkey
, destp
->h_charkey
);
978 for ( i
=0; i
< NCACHED
; i
++ ) {
979 BLSWAP_COPY ( srcp
->spares
[i
] , destp
->spares
[i
]);
980 BSSWAP_COPY ( srcp
->bitmaps
[i
] , destp
->bitmaps
[i
]);
994 BLSWAP(hdrp
->version
);
995 BLSWAP(hdrp
->lorder
);
997 BLSWAP(hdrp
->bshift
);
1000 BLSWAP(hdrp
->sshift
);
1001 BLSWAP(hdrp
->max_bucket
);
1002 BLSWAP(hdrp
->high_mask
);
1003 BLSWAP(hdrp
->low_mask
);
1004 BLSWAP(hdrp
->ffactor
);
1005 BLSWAP(hdrp
->nkeys
);
1006 BLSWAP(hdrp
->hdrpages
);
1007 BLSWAP(hdrp
->h_charkey
);
1008 for ( i
=0; i
< NCACHED
; i
++ ) {
1009 BLSWAP ( hdrp
->spares
[i
] );
1010 BSSWAP ( hdrp
->bitmaps
[i
] );