1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 1996, 1997, 1998, 1999
5  *	Sleepycat Software.  All rights reserved.
6  */
7 /*
8  * Copyright (c) 1990, 1993, 1994, 1995, 1996
9  *	Keith Bostic.  All rights reserved.
10  */
11 /*
12  * Copyright (c) 1990, 1993, 1994, 1995
13  *	The Regents of the University of California.  All rights reserved.
14  *
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions
17  * are met:
18  * 1. Redistributions of source code must retain the above copyright
19  *    notice, this list of conditions and the following disclaimer.
20  * 2. Redistributions in binary form must reproduce the above copyright
21  *    notice, this list of conditions and the following disclaimer in the
22  *    documentation and/or other materials provided with the distribution.
23  * 3. Neither the name of the University nor the names of its contributors
24  *    may be used to endorse or promote products derived from this software
25  *    without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  */
39 
40 #include "db_config.h"
41 
42 #ifndef lint
43 static const char sccsid[] = "@(#)db_conv.c	11.4 (Sleepycat) 11/10/99";
44 #endif /* not lint */
45 
46 #ifndef NO_SYSTEM_INCLUDES
47 #include <sys/types.h>
48 
49 #include <errno.h>
50 #include <string.h>
51 #endif
52 
53 #include "db_int.h"
54 #include "db_page.h"
55 #include "db_swap.h"
56 #include "db_am.h"
57 #include "btree.h"
58 #include "hash.h"
59 #include "qam.h"
60 
61 /*
62  * CDB___db_pgin --
63  *	Primary page-swap routine.
64  *
65  * PUBLIC: int CDB___db_pgin __P((db_pgno_t, void *, DBT *));
66  */
67 int
CDB___db_pgin(pg,pp,cookie)68 CDB___db_pgin(pg, pp, cookie)
69 	db_pgno_t pg;
70 	void *pp;
71 	DBT *cookie;
72 {
73 	DB_PGINFO *pginfo;
74 
75 	pginfo = (DB_PGINFO *)cookie->data;
76 
77 	switch (((PAGE *)pp)->type) {
78 	case P_HASH:
79 	case P_HASHMETA:
80 	case P_INVALID:
81 		return (CDB___ham_pgin(pg, pp, cookie));
82 	case P_BTREEMETA:
83 	case P_IBTREE:
84 	case P_IRECNO:
85 	case P_LBTREE:
86 	case P_LRECNO:
87 	case P_DUPLICATE:
88 	case P_OVERFLOW:
89 		return (CDB___bam_pgin(pg, pp, cookie));
90 	case P_QAMMETA:
91 	case P_QAMDATA:
92 		return (CDB___qam_pgin_out(pg, pp, cookie));
93 	default:
94 		break;
95 	}
96 	return (EINVAL);
97 }
98 
99 /*
100  * CDB___db_pgout --
101  *	Primary page-swap routine.
102  *
103  * PUBLIC: int CDB___db_pgout __P((db_pgno_t, void *, DBT *));
104  */
105 int
CDB___db_pgout(pg,pp,cookie)106 CDB___db_pgout(pg, pp, cookie)
107 	db_pgno_t pg;
108 	void *pp;
109 	DBT *cookie;
110 {
111 	DB_PGINFO *pginfo;
112 
113 	pginfo = (DB_PGINFO *)cookie->data;
114 
115 	switch (((PAGE *)pp)->type) {
116 	case P_HASH:
117 	case P_HASHMETA:
118 	case P_INVALID:
119 		return (CDB___ham_pgout(pg, pp, cookie));
120 	case P_BTREEMETA:
121 	case P_IBTREE:
122 	case P_IRECNO:
123 	case P_LBTREE:
124 	case P_LRECNO:
125 	case P_DUPLICATE:
126 	case P_OVERFLOW:
127 		return (CDB___bam_pgout(pg, pp, cookie));
128 	case P_QAMMETA:
129 	case P_QAMDATA:
130 		return (CDB___qam_pgin_out(pg, pp, cookie));
131 	default:
132 		break;
133 	}
134 	return (EINVAL);
135 }
136 
137 /*
138  * CDB___db_metaswap --
139  *	Byteswap the common part of the meta-data page.
140  *
141  * PUBLIC: void CDB___db_metaswap __P((PAGE *));
142  */
143 void
CDB___db_metaswap(pg)144 CDB___db_metaswap(pg)
145 	PAGE *pg;
146 {
147 	u_int8_t *p;
148 
149 	p = (u_int8_t *)pg;
150 
151 	/* Swap the meta-data information. */
152 	SWAP32(p);	/* lsn.file */
153 	SWAP32(p);	/* lsn.offset */
154 	SWAP32(p);	/* pgno */
155 	SWAP32(p);	/* magic */
156 	SWAP32(p);	/* version */
157 	SWAP32(p);	/* pagesize */
158 	p += 4;		/* unused, page type, unused, unused */
159 	SWAP32(p);	/* free */
160 	SWAP32(p);	/* flags */
161 }
162 
163 /*
164  * CDB___db_byteswap --
165  *	Byteswap a page.
166  *
167  * PUBLIC: int CDB___db_byteswap __P((db_pgno_t, PAGE *, size_t, int));
168  */
169 int
CDB___db_byteswap(pg,h,pagesize,pgin)170 CDB___db_byteswap(pg, h, pagesize, pgin)
171 	db_pgno_t pg;
172 	PAGE *h;
173 	size_t pagesize;
174 	int pgin;
175 {
176 	BINTERNAL *bi;
177 	BKEYDATA *bk;
178 	BOVERFLOW *bo;
179 	RINTERNAL *ri;
180 	db_indx_t i, len, tmp;
181 	u_int8_t *p, *end;
182 
183 	COMPQUIET(pg, 0);
184 
185 	if (pgin) {
186 		M_32_SWAP(h->lsn.file);
187 		M_32_SWAP(h->lsn.offset);
188 		M_32_SWAP(h->pgno);
189 		M_32_SWAP(h->prev_pgno);
190 		M_32_SWAP(h->next_pgno);
191 		M_16_SWAP(h->entries);
192 		M_16_SWAP(h->hf_offset);
193 	}
194 
195 	switch (h->type) {
196 	case P_HASH:
197 		for (i = 0; i < NUM_ENT(h); i++) {
198 			if (pgin)
199 				M_16_SWAP(h->inp[i]);
200 
201 			switch (HPAGE_TYPE(h, i)) {
202 			case H_KEYDATA:
203 				break;
204 			case H_DUPLICATE:
205 				len = LEN_HKEYDATA(h, pagesize, i);
206 				p = HKEYDATA_DATA(P_ENTRY(h, i));
207 				for (end = p + len; p < end;) {
208 					if (pgin) {
209 						P_16_SWAP(p);
210 						memcpy(&tmp,
211 						    p, sizeof(db_indx_t));
212 						p += sizeof(db_indx_t);
213 					} else {
214 						memcpy(&tmp,
215 						    p, sizeof(db_indx_t));
216 						SWAP16(p);
217 					}
218 					p += tmp;
219 					SWAP16(p);
220 				}
221 				break;
222 			case H_OFFDUP:
223 				p = HOFFPAGE_PGNO(P_ENTRY(h, i));
224 				SWAP32(p);			/* pgno */
225 				break;
226 			case H_OFFPAGE:
227 				p = HOFFPAGE_PGNO(P_ENTRY(h, i));
228 				SWAP32(p);			/* pgno */
229 				SWAP32(p);			/* tlen */
230 				break;
231 			}
232 
233 		}
234 
235 		/*
236 		 * The offsets in the inp array are used to determine
237 		 * the size of entries on a page; therefore they
238 		 * cannot be converted until we've done all the
239 		 * entries.
240 		 */
241 		if (!pgin)
242 			for (i = 0; i < NUM_ENT(h); i++)
243 				M_16_SWAP(h->inp[i]);
244 		break;
245 	case P_LBTREE:
246 	case P_LRECNO:
247 	case P_DUPLICATE:
248 		for (i = 0; i < NUM_ENT(h); i++) {
249 			if (pgin)
250 				M_16_SWAP(h->inp[i]);
251 
252 			/*
253 			 * In the case of on-page duplicates, key information
254 			 * should only be swapped once.
255 			 */
256 			if (h->type == P_LBTREE && i > 1) {
257 				if (pgin) {
258 					if (h->inp[i] == h->inp[i - 2])
259 						continue;
260 				} else {
261 					M_16_SWAP(h->inp[i]);
262 					if (h->inp[i] == h->inp[i - 2])
263 						continue;
264 					M_16_SWAP(h->inp[i]);
265 				}
266 			}
267 
268 			bk = GET_BKEYDATA(h, i);
269 			switch (B_TYPE(bk->type)) {
270 			case B_KEYDATA:
271 				M_16_SWAP(bk->len);
272 				break;
273 			case B_DUPLICATE:
274 			case B_OVERFLOW:
275 				bo = (BOVERFLOW *)bk;
276 				M_32_SWAP(bo->pgno);
277 				M_32_SWAP(bo->tlen);
278 				break;
279 			}
280 
281 			if (!pgin)
282 				M_16_SWAP(h->inp[i]);
283 		}
284 		break;
285 	case P_IBTREE:
286 		for (i = 0; i < NUM_ENT(h); i++) {
287 			if (pgin)
288 				M_16_SWAP(h->inp[i]);
289 
290 			bi = GET_BINTERNAL(h, i);
291 			M_16_SWAP(bi->len);
292 			M_32_SWAP(bi->pgno);
293 			M_32_SWAP(bi->nrecs);
294 
295 			switch (B_TYPE(bi->type)) {
296 			case B_KEYDATA:
297 				break;
298 			case B_DUPLICATE:
299 			case B_OVERFLOW:
300 				bo = (BOVERFLOW *)bi->data;
301 				M_32_SWAP(bo->pgno);
302 				M_32_SWAP(bo->tlen);
303 				break;
304 			}
305 
306 			if (!pgin)
307 				M_16_SWAP(h->inp[i]);
308 		}
309 		break;
310 	case P_IRECNO:
311 		for (i = 0; i < NUM_ENT(h); i++) {
312 			if (pgin)
313 				M_16_SWAP(h->inp[i]);
314 
315 			ri = GET_RINTERNAL(h, i);
316 			M_32_SWAP(ri->pgno);
317 			M_32_SWAP(ri->nrecs);
318 
319 			if (!pgin)
320 				M_16_SWAP(h->inp[i]);
321 		}
322 		break;
323 	case P_OVERFLOW:
324 	case P_INVALID:
325 		/* Nothing to do. */
326 		break;
327 	default:
328 		return (EINVAL);
329 	}
330 
331 	if (!pgin) {
332 		/* Swap the header information. */
333 		M_32_SWAP(h->lsn.file);
334 		M_32_SWAP(h->lsn.offset);
335 		M_32_SWAP(h->pgno);
336 		M_32_SWAP(h->prev_pgno);
337 		M_32_SWAP(h->next_pgno);
338 		M_16_SWAP(h->entries);
339 		M_16_SWAP(h->hf_offset);
340 	}
341 	return (0);
342 }
343