1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 1996, 1997, 1998, 1999, 2000
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 "config.h"
41 
42 #ifndef lint
43 static const char revid[] = "$Id: db_conv.c,v 1.5 2014/04/17 20:27:26 sebdiaz Exp $";
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_ENV *, db_pgno_t, void *, DBT *));
66  */
67 int
CDB___db_pgin(dbenv,pg,pp,cookie)68 CDB___db_pgin(dbenv, pg, pp, cookie)
69 	DB_ENV *dbenv;
70 	db_pgno_t pg;
71 	void *pp;
72 	DBT *cookie;
73 {
74 
75 
76 
77 	switch (TYPE(pp)) {
78 	case P_HASH:
79 	case P_HASHMETA:
80 	case P_INVALID:
81 		return (CDB___ham_pgin(dbenv, pg, pp, cookie));
82 	case P_BTREEMETA:
83 	case P_IBTREE:
84 	case P_IRECNO:
85 	case P_LBTREE:
86 	case P_LDUP:
87 	case P_LRECNO:
88 	case P_OVERFLOW:
89 		return (CDB___bam_pgin(dbenv, pg, pp, cookie));
90 	case P_QAMMETA:
91 	case P_QAMDATA:
92 		return (CDB___qam_pgin_out(dbenv, pg, pp, cookie));
93 	default:
94 		break;
95 	}
96 	return (CDB___db_unknown_type(dbenv, "CDB___db_pgin", ((PAGE *)pp)->type));
97 }
98 
99 /*
100  * CDB___db_pgout --
101  *	Primary page-swap routine.
102  *
103  * PUBLIC: int CDB___db_pgout __P((DB_ENV *, db_pgno_t, void *, DBT *));
104  */
105 int
CDB___db_pgout(dbenv,pg,pp,cookie)106 CDB___db_pgout(dbenv, pg, pp, cookie)
107 	DB_ENV *dbenv;
108 	db_pgno_t pg;
109 	void *pp;
110 	DBT *cookie;
111 {
112 
113 	switch (TYPE(pp)) {
114 	case P_HASH:
115 	case P_HASHMETA:
116 	case P_INVALID:
117 		return (CDB___ham_pgout(dbenv, pg, pp, cookie));
118 	case P_BTREEMETA:
119 	case P_IBTREE:
120 	case P_IRECNO:
121 	case P_LBTREE:
122 	case P_LDUP:
123 	case P_LRECNO:
124 	case P_OVERFLOW:
125 		return (CDB___bam_pgout(dbenv, pg, pp, cookie));
126 	case P_QAMMETA:
127 	case P_QAMDATA:
128 		return (CDB___qam_pgin_out(dbenv, pg, pp, cookie));
129 	default:
130 		break;
131 	}
132 	return (CDB___db_unknown_type(dbenv, "CDB___db_pgout", ((PAGE *)pp)->type));
133 }
134 
135 /*
136  * CDB___db_metaswap --
137  *	Byteswap the common part of the meta-data page.
138  *
139  * PUBLIC: void CDB___db_metaswap __P((PAGE *));
140  */
141 void
CDB___db_metaswap(pg)142 CDB___db_metaswap(pg)
143 	PAGE *pg;
144 {
145 	u_int8_t *p;
146 
147 	p = (u_int8_t *)pg;
148 
149 	/* Swap the meta-data information. */
150 	SWAP32(p);	/* lsn.file */
151 	SWAP32(p);	/* lsn.offset */
152 	SWAP32(p);	/* pgno */
153 	SWAP32(p);	/* magic */
154 	SWAP32(p);	/* version */
155 	SWAP32(p);	/* pagesize */
156 	p += 4;		/* unused, page type, unused, unused */
157 	SWAP32(p);	/* free */
158 	SWAP32(p);	/* alloc_lsn part 1 */
159 	SWAP32(p);	/* alloc_lsn part 2 */
160 	SWAP32(p);	/* cached key count */
161 	SWAP32(p);	/* cached record count */
162 	SWAP32(p);	/* flags */
163 }
164 
165 /*
166  * CDB___db_byteswap --
167  *	Byteswap a page.
168  *
169  * PUBLIC: int CDB___db_byteswap __P((DB_ENV *, db_pgno_t, PAGE *, size_t, int));
170  */
171 int
CDB___db_byteswap(dbenv,pg,h,pagesize,pgin)172 CDB___db_byteswap(dbenv, pg, h, pagesize, pgin)
173 	DB_ENV *dbenv;
174 	db_pgno_t pg;
175 	PAGE *h;
176 	size_t pagesize;
177 	int pgin;
178 {
179 	if(pg){}
180 	BINTERNAL *bi;
181 	BKEYDATA *bk;
182 	BOVERFLOW *bo;
183 	RINTERNAL *ri;
184 	db_indx_t i, len, tmp;
185 	u_int8_t *p, *end;
186 
187 	COMPQUIET(pg, 0);
188 
189 	if (pgin) {
190 		M_32_SWAP(h->lsn.file);
191 		M_32_SWAP(h->lsn.offset);
192 		M_32_SWAP(h->pgno);
193 		M_32_SWAP(h->prev_pgno);
194 		M_32_SWAP(h->next_pgno);
195 		M_16_SWAP(h->entries);
196 		M_16_SWAP(h->hf_offset);
197 	}
198 
199 	switch (TYPE(h)) {
200 	case P_HASH:
201 		for (i = 0; i < NUM_ENT(h); i++) {
202 			if (pgin)
203 				M_16_SWAP(h->inp[i]);
204 
205 			switch (HPAGE_TYPE(h, i)) {
206 			case H_KEYDATA:
207 				break;
208 			case H_DUPLICATE:
209 				len = LEN_HKEYDATA(h, pagesize, i);
210 				p = HKEYDATA_DATA(P_ENTRY(h, i));
211 				for (end = p + len; p < end;) {
212 					if (pgin) {
213 						P_16_SWAP(p);
214 						memcpy(&tmp,
215 						    p, sizeof(db_indx_t));
216 						p += sizeof(db_indx_t);
217 					} else {
218 						memcpy(&tmp,
219 						    p, sizeof(db_indx_t));
220 						SWAP16(p);
221 					}
222 					p += tmp;
223 					SWAP16(p);
224 				}
225 				break;
226 			case H_OFFDUP:
227 				p = HOFFPAGE_PGNO(P_ENTRY(h, i));
228 				SWAP32(p);			/* pgno */
229 				break;
230 			case H_OFFPAGE:
231 				p = HOFFPAGE_PGNO(P_ENTRY(h, i));
232 				SWAP32(p);			/* pgno */
233 				SWAP32(p);			/* tlen */
234 				break;
235 			}
236 
237 		}
238 
239 		/*
240 		 * The offsets in the inp array are used to determine
241 		 * the size of entries on a page; therefore they
242 		 * cannot be converted until we've done all the
243 		 * entries.
244 		 */
245 		if (!pgin)
246 			for (i = 0; i < NUM_ENT(h); i++)
247 				M_16_SWAP(h->inp[i]);
248 		break;
249 	case P_LBTREE:
250 	case P_LDUP:
251 	case P_LRECNO:
252 		for (i = 0; i < NUM_ENT(h); i++) {
253 			if (pgin)
254 				M_16_SWAP(h->inp[i]);
255 
256 			/*
257 			 * In the case of on-page duplicates, key information
258 			 * should only be swapped once.
259 			 */
260 			if (TYPE(h) == P_LBTREE && i > 1) {
261 				if (pgin) {
262 					if (h->inp[i] == h->inp[i - 2])
263 						continue;
264 				} else {
265 					M_16_SWAP(h->inp[i]);
266 					if (h->inp[i] == h->inp[i - 2])
267 						continue;
268 					M_16_SWAP(h->inp[i]);
269 				}
270 			}
271 
272 			bk = GET_BKEYDATA(h, i);
273 			switch (B_TYPE(bk->type)) {
274 			case B_KEYDATA:
275 				M_16_SWAP(bk->len);
276 				break;
277 			case B_DUPLICATE:
278 			case B_OVERFLOW:
279 				bo = (BOVERFLOW *)bk;
280 				M_32_SWAP(bo->pgno);
281 				M_32_SWAP(bo->tlen);
282 				break;
283 			}
284 
285 			if (!pgin)
286 				M_16_SWAP(h->inp[i]);
287 		}
288 		break;
289 	case P_IBTREE:
290 		for (i = 0; i < NUM_ENT(h); i++) {
291 			if (pgin)
292 				M_16_SWAP(h->inp[i]);
293 
294 			bi = GET_BINTERNAL(h, i);
295 			M_16_SWAP(bi->len);
296 			M_32_SWAP(bi->pgno);
297 			M_32_SWAP(bi->nrecs);
298 
299 			switch (B_TYPE(bi->type)) {
300 			case B_KEYDATA:
301 				break;
302 			case B_DUPLICATE:
303 			case B_OVERFLOW:
304 				bo = (BOVERFLOW *)bi->data;
305 				M_32_SWAP(bo->pgno);
306 				M_32_SWAP(bo->tlen);
307 				break;
308 			}
309 
310 			if (!pgin)
311 				M_16_SWAP(h->inp[i]);
312 		}
313 		break;
314 	case P_IRECNO:
315 		for (i = 0; i < NUM_ENT(h); i++) {
316 			if (pgin)
317 				M_16_SWAP(h->inp[i]);
318 
319 			ri = GET_RINTERNAL(h, i);
320 			M_32_SWAP(ri->pgno);
321 			M_32_SWAP(ri->nrecs);
322 
323 			if (!pgin)
324 				M_16_SWAP(h->inp[i]);
325 		}
326 		break;
327 	case P_OVERFLOW:
328 	case P_INVALID:
329 		/* Nothing to do. */
330 		break;
331 	default:
332 		return (CDB___db_unknown_type(dbenv, "CDB___db_byteswap", h->type));
333 	}
334 
335 	if (!pgin) {
336 		/* Swap the header information. */
337 		M_32_SWAP(h->lsn.file);
338 		M_32_SWAP(h->lsn.offset);
339 		M_32_SWAP(h->pgno);
340 		M_32_SWAP(h->prev_pgno);
341 		M_32_SWAP(h->next_pgno);
342 		M_16_SWAP(h->entries);
343 		M_16_SWAP(h->hf_offset);
344 	}
345 	return (0);
346 }
347